一、事务基本要素

原子性

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性

在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

隔离性

数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读已提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

持久性

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

二、事务并发

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
串行化(serializable)

脏读

事务A 事务B 说明
BEGIN; BEGIN;
INSERT INTO students VALUES (5, ‘赵六’);
事务 A 新增一条数据。

SELECT * FROM students;
事务 B 读到了事务 A 新增却还没提交的数据。
ROLLBACK;
要是这时事务 A 回滚操作。

SELECT * FROM students; 事务 B 再次查询发现已经没有了「赵六」的数据。

COMMIT;

不可重复读

事务A 事务B 说明
BEGIN; BEGIN;
SELECT name FROM WHERE id = 1; 事务 B 查询 id = 1 的是「张三」。
UPDATE students SET name = ‘张三三’ WHERE id = 1; 事务 A 修改 id = 1 为「张三三」。
COMMIT;
SELECT name FROM WHERE id = 1; 事务 B 再次查询 id = 1 的已经改成「张三三」。
COMMIT;

幻读

事务A 事务B 说明
BEGIN; BEGIN;
SELECT * FROM students WHERE id BETWEEN 1 AND 5; 事务 B 查询某范围内的数据。
INSERT INTO students VALUES (4, ‘赵六’); 事务 A 新增一条数据。
COMMIT;
SELECT * FROM students WHERE id BETWEEN 1 AND 5; 事务 B 再次查询发现数据发生更改。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。