Mysql的事务
一、事务的ACID特性
1、原子性(atomicity)
原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚
2、一致性(consistency)
一致性是指事务执行前后,数据从一个 合法性状态
变换到另外一个 合法性状态
。
举例:
同一事务下,账户转账,A账户减200,B账户就要加200,符合预期的才是一致性
3、隔离型(isolation)
事务的隔离性是指一个事务的执行 不能被其他事务干扰
,即一个事务内部的操作及使用的数据对 并发
的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
举例:
A事务和B事务各自执行,互不影响。
4、持久性(durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是 永久性的 ,接下来的其他操作和数据库故障不应该对其有任何影响。
二、隔离性引起的并发问题
1、脏写( Dirty Write )
一个事务写了没提交,另外一个接着写了
对于两个事务 Session A
、Session B
,如果事务Session A 修改了 另一个 未提交 事务Session B
修改过 的数据,那就意味着发生了 脏写
举例:
账户余额为100,B事务增加了100,但是事务未提交,A事务在B的基础上将余额减少了100,如果B事务回滚就会引起数据错乱,这种现象就是脏写。
2、脏读( Dirty Read )
一个事务写了没提交,另外一个接着读了(读未提交:读到了一个事务未提交的内容)
对于两个事务 Session A
、Session B
,Session A 读取 了已经被 Session B 更新 但还 没有被提交 的字段。之后若 Session B 回滚 ,Session A 读取 的内容就是 临时且无效
的
举例:
账户余额为100,B事务增加了100,但是事务未提交,A事务读取到的账户金额是200,然后在200基础上执行后续操作,如果B事务回滚就会引起数据错乱,这种现象就是脏读。
3、不可重复读( Non-Repeatable Read )
一个事务读取了一条数据,另一个事务更新了该条数据,之前那个事务再读的话,数据就变了
注意:不可重复读是针对同一条数据出现了前后不一致的现象
对于两个事务Session A
、Session B
,Session A 读取
了一个结果,然后 Session B 更新
了该数据。 之后Session A 再次读取
同一个数据, 结果就不同
了。那就意味着发生了不可重复读。
举例:
账户余额为100,A事务第一次读取到的账户金额是100,B事务增加了100,A事务再次读取变成了200,A事务发生了不可重复读现象。
4、幻读( Phantom )
一个事务第一次读取表中没有数据,此时另外一个事务增加了一条数据,之前事务再次读取发现多了一条数据
注意:幻读是针对整个表的数据,出现了读取前后不一致的现象
对于两个事务Session A
、Session B
, Session A 从一个表中 读取
了数据, 然后 Session B 在该表中 插入
了一些新的行。 之后, 如果 Session A 再次读取
同一个表, 就会多出几行。那就意味着发生了幻读。
三、SQL中的四种隔离级别
READ UNCOMMITTED :
读未提交
,在该隔离级别,所有事务都可以看到其他未提交事务的执行结果
。不能避免脏读、不可重复读、幻读。READ COMMITTED :
读已提交
,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可重复读、幻读问题仍然存在。REPEATABLE READ :
可重复读
,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍然存在。这是MySQL的默认隔离级别
。SERIALIZABLE :
可串行化
,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免,但性能十分低下
。能避免脏读、不可重复读和幻读。
如何解决幻读?
解决幻读的方式有很多,但是它们的核心思想就是一个事务在操作某张表数据的时候,另外一个事务不允许新增或者删除这张表中的数据了。解决幻读的方式主要有以下几种:
将事务隔离级别调整为
SERIALIZABLE
。在可重复读的事务级别下,给事务操作的这张表添加表锁。
在可重复读的事务级别下,给事务操作的这张表添加
Next-key Lock(Record Lock+Gap Lock)
。如何设置事务的隔离级别?
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别' #其中,隔离级别格式: > READ-UNCOMMITTED > READ-COMMITTED > REPEATABLE-READ > SERIALIZABLE