数据库事务及隔离级别
四大特性(ACID)
- 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。 - 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。 - 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。 - 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
隔离级别详解
如果不对数据库进行并发控制,可能会产生异常情况:
- 脏读(Dirty Read)
当一个事务读取其他事务尚未提交的修改时,产生脏读。
同一事务内不是脏读。 一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚,也就是说读取出的数据其实是错误的。 - 非重复读(Nonrepeatable Read)
重点在于update和delete。一个事务对同一行数据重复读取两次,但是却得到了不同的结果。同一查询在同一事务中多次进行,由于其他事务已提交修改或删除,每次返回不同的结果集,此时发生非重复读。 - 幻像读(Phantom Reads)
重点在于insert。事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有其他事务插入数据造成的。
当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。 - 丢失修改(Lost Update)
第一类:当两个事务更新相同的数据源,如果第一个事务被提交,第二个却被撤销,那么连同第一个事务做的更新也被撤销。
第二类:有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。
隔离级别包含四种:
- 串行化 (Serializable)
直译就是"序列化",意思是说这个事务执行的时候不允许别的事务并发执行。完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。 - 可重复读(Repeatable Read):
直译就是"可以重复读",这是说在同一个事务里面先后执行同一个查询语句的时候,得到的结果是一样的。 - 读取已提交(Read Committed)
直译就是"读提交",意思就是一个事务能够读取到其他事务已经提交的数据。Oracle等多数数据库默认都是该级别。 - 读取未提交(Read Uncommitted)
直译就是"读未提交",意思就是一个事务能够读取到其他事务尚未提交的数据。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 串行化 (Serializable) | × | × | × |
| 可重复读(Repeatable Read) | × | × | √ |
| 读取已提交(Read Committed) | × | √ | √ |
| 读取未提交(Read Uncommitted) | √ | √ | √ |
参考:
https://www.ibm.com/developerworks/cn/opensource/os-mysql-transaction-isolation-levels-and-locks/index.html
https://tech.meituan.com/2014/08/20/innodb-lock.html

浙公网安备 33010602011771号