mysql事务之间的隔离级别
事务间未做隔离,会引起下面这些问题。
1、脏读:一个事务可读到另外一个尚未commit的事务中的数据。
2、不可重复读:在一个事务中,读取同一个数据 a,b,按顺序读取,在读a b 之间,另外一个事务修改了这个数值,并且提交了。这时,在这同一事务中,两次读取的值就不同了。
3、幻读:事务A,更新日期2017至2018之间的数据,将字段test_value都置为0。
但是此时,事务B又新插入一条2017至2018之间的数据,test_value为1。
最后的结果,事务A在表面上没有更新全部的,而漏掉了一条。
mysql的事务间的隔离级别分为下面几个级别(由高到低)
1、串行锁(可解决脏读,不可重复读,幻读的问题)
2、可重复读
3、读已commit
4、无隔离
四种事物隔离级别由低到高分别可以避免脏读、不可重复读和幻读。但是随着事物隔离级别的提高,系统开销也会不断提升。MySQL默认的事物隔离级别是第三级(Repeatable read)也是最常用的级别。
脏读 | 不可重复读 | 幻读 | |
Read uncommitted | √ | √ | √ |
Read committed | √ | √ | |
Repeatable read(默认) | √ | ||
Serializable |
一、Read uncommitted
处在Read uncommitted级别的事物能够被其他事物读取语句间的数据,因此会出现其它事物读取了还未提交的数据。如果当前事物不发生回滚,则不会产生问题。效率最高,但不推荐。
二、Read committed
当前事物隔离级别,其它事物无法读取到已经被修改但是还未被提交的数据。但是其它事物线程也不会被阻塞,这意味着如果存在并发事物尝试读取当前正在被修改的数据行时可能会读取到原始数据。要避免这样的问题需要当有事物正在修改行级数据的时候,其它事物无论读或者写都必须被阻塞。
上表两次发出的select A from语句都是对同一行数据的查询。由于两条事物相互隔离,因此不会读到另一条线程中的操作数。但是依然可以读取当前行的原始数据,因此会造成两次读取的结果不一致。
三、Repeatable read(默认)
Repeatable read级别是MySQL默认的隔离级别,除非使用者明确修改。当前级别下的事物会同时为当前行增加读写的行级锁或页级锁,操作完毕以后随即unlock tables;如果在并发的事物中存在读取当前行数据的行为时,事物将被阻塞。直到获取行级锁的时候才能够继续操作并同时阻塞别的线程。
在当前隔离级别下,大部分的数据操作都是安全的。唯一可能发生问题的情况是事物需要插入数据或删除数据的时候,由于行级锁并未对表锁定。因此对于数据表的遍历可能会发生幻读错误。解决幻读问题的关键事物对任何数据表的操作,同时使用表级锁。其它任何并发事物都必须等待当前操作完成。从宏观上观察,就是杜绝了事物的并发操作。
四、Serializable
序列化事物是最高的事物隔离级别,也是最占用系统资源的操作。可以避免所有问题,但也不被推荐。
相关命令
1.查看当前会话隔离级别
select @@tx_isolation;
2.查看系统当前隔离级别
select @@global.tx_isolation;
3.设置当前会话隔离级别
set session transaction isolatin level repeatable read;
4.设置系统当前隔离级别
set global transaction isolation level repeatable read;
5.命令行,开始事务时
set autocommit=off 或者 start transaction