事务具有4个特征
- Atomicity(原子性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
数据库隔离级别
在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同
- 未提交读 (READ_UNCOMMITTED)
- 提交读 (READ_COMMITTED)
- 可重复读 (REPEATABLE_READ)
- 可串行化 (SERIALIZABLE)
查看&设置数据库隔离级别
查看数据库当前隔离级别
mysql> show SESSION variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.02 sec)
设置数据库隔离级别
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
mysql> set SESSION transaction_isolation ='read-uncommitted';
Query OK, 0 rows affected (0.00 sec)
mysql> show SESSION variables like '%isolation%';
+-----------------------+------------------+
| Variable_name | Value |
+-----------------------+------------------+
| transaction_isolation | READ-UNCOMMITTED |
+-----------------------+------------------+
1 row in set (0.00 sec)
数据库隔离级别以及产生的问题
隔离级别 | 是否出现第一类丢失更新 | 是否出现脏读 | 是否出现不可重复读 | 是否出现幻读 | 是否出现第二类丢失更新 |
---|---|---|---|---|---|
Read Uncommited | 否 | 是 | 是 | 是 | 是 |
Read Commited | 否 | 否 | 是 | 是 | 是 |
Repeatable Read | 否 | 否 | 否 | 是 | 否 |
Serializable | 否 | 否 | 否 | 否 | 否 |
第一类丢失更新
撤销一个事务时, 把其他事务已经提交的更新数据覆盖(此情况在事务中不可能出现, 因为一个事务中修改时此记录已加锁, 必须等待此事务完成后另一个事务才可以继续UPDATE)
脏读
一个事务读到另一个事务尚未提交的修改,就是脏读。
不可重复读
指的是一个事务内多次读取同一个数据集合。在这个事务还没有结束时,另一个事务对数据进行了DML操作,导致第一个事务两次读取数据不一样。
和脏读的区别在于:脏读读取到的时未提交的数据,不可重复读,读取的是已经提交的内容。
一般来说不可重复读是可以被接受的,本就是已经提交的数据,不会带来很大的问题。
幻读
幻读,针对的是Insert操作。事务1读取指定的where子句所返回的一些行。然后,事务2插入一个新行,这个新行也满足事务1使用的查询where子句。然后事务1再次使用相同的查询读取行,但是现在它看到了事务2刚插入的行。
在快照读的情况下,MySQL 通过 MVCC 来避免幻读。
在当前读的情况下,MySQL 通过 next-key 来避免幻读。
第二类丢失更新
这是不可重复读中的特例, 一个事务覆盖另一个事务已提交的更新数据
复现各种情况
未提交读下的脏读、幻读、不可重复读
提交读下的脏读、幻读、不可重复读
可重复读下的脏读、幻读、不可重复读
查看&设置数据库隔离级别
查看数据库当前隔离级别
mysql> show SESSION variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.02 sec)