This(Consistency)does not guarantee correctness of the transaction in all ways the application programmer might have wanted (that is the responsibility of application-level code) but merely that any programming errors cannot result in the violation of any defined database constraints.
一致性
-- 定义一致性约束 CREATE TABLE accounts ( id INT PRIMARY KEY, balance DECIMAL NOT NULL CHECK (balance >= 0), -- 确保余额非负 customer_id INT NOT NULL, FOREIGN KEY (customer_id) REFERENCES customers(id) -- 引用完整性 ); -- 尝试违反一致性的操作(会被拒绝) UPDATE accounts SET balance = -100 WHERE id = 1;
The result of successfully committing a group of transactions is inconsistent with all possible orderings of running those transactions one at a time.
A transaction reads data written by a concurrent uncommitted transaction.
-- 事务ABEGIN;UPDATE accounts SET balance = balance - 100 WHERE id = 1;-- 此时未提交-- 事务BBEGIN;SELECT balance FROM accounts WHERE id = 1; -- 读取到事务A未提交的数据-- 基于这个可能不正确的余额做决策-- 事务AROLLBACK; -- 撤销修改,事务B读取的数据变成了"脏数据"
A transaction re-reads data it has previously read and finds that data has been modified by another transaction (that committed since the initial read).
-- 事务ABEGIN;SELECT balance FROM accounts WHERE id = 1; -- 读取余额为1000-- 事务BBEGIN;UPDATE accounts SET balance = balance - 100 WHERE id = 1;COMMIT;-- 事务ASELECT balance FROM accounts WHERE id = 1; -- 再次读取,余额变为900-- 同一事务内两次读取结果不一致COMMIT;
A transaction re-executes a query returning a set of rows that satisfy a search condition and finds that the set of rows satisfying the condition has changed due to another recently-committed transaction.
-- 事务ABEGIN;SELECT * FROM accounts WHERE balance > 500; -- 返回5条记录-- 事务BBEGIN;INSERT INTO accounts (id, name, balance) VALUES (6, 'Tom', 600);COMMIT;-- 事务ASELECT * FROM accounts WHERE balance > 500; -- 返回6条记录,多了一条"幻影"记录COMMIT;
Transaction A and Transaction B read and updates the same data, The update of Transaction A is lost because Transaction B overwrites it.
-- 事务A和事务B同时读取账户余额1000-- 事务A将余额增加100,变为1100-- 事务B将余额减少200,变为800-- 如果事务B后提交,最终余额为800,事务A的更新被丢失-- 事务ABEGIN;SELECT balance FROM accounts WHERE id = 1; -- 读取余额为1000-- 计算新余额 1000 + 100 = 1100UPDATE accounts SET balance = 1100 WHERE id = 1;COMMIT;-- 事务B(几乎同时)BEGIN;SELECT balance FROM accounts WHERE id = 1; -- 读取余额为1000-- 计算新余额 1000 - 200 = 800UPDATE accounts SET balance = 800 WHERE id = 1;COMMIT; -- 事务B的更新覆盖了事务A的更新
Isolation Level | Dirty Read | Nonrepeatable Read | Phantom Read | Serialization Anomaly |
---|---|---|---|---|
Read uncommitted | Allowed, but not in PG | Possible | Possible | Possible |
Read committed | Not possible | Possible | Possible | Possible |
Repeatable read | Not possible | Not possible | Allowed, but not in PG | Possible |
Serializable | Not possible | Not possible | Not possible | Not possible |
-- 查询当前会话隔离级别SELECT @@tx_isolation; -- mysqlSELECT current_setting('transaction_isolation'); -- postgresql-- 设置当前会话隔离级别SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;-- 设置全局隔离级别SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- <READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE>
postgresql-transaction-isolation-levels
zhihu
DB 多表查询&事务