mysql有四种隔离机制
SELECT @@global.tx_isolation; #查询全局隔离级别,默认为REPEATABLE-READ.
SELECT @@session.tx_isolation; #查询当前会话隔离级别.
脏读测试
脏读的级别是"read Uncommitted",翻译过来也就是"读,没有提交",操作上就是会读取事务未提交的数据,比如会话1将值从200修改到500,此时还未提交,会话2就可以直接读取到未提交的500数值。
- 开启两个mysql会话。
- 设置mysql会话隔离级别为read Uncommitted,并开启事务.
SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted; #设置为"读 未提交"级别
set autocommit = 0;
- 事务1查询数据
- 事务2 修改id为1的name为11.此时并不提交.
5.事务1再次查看数据.
此时,虽然事务2还未提交,但是事务1已经可以读取到未提交而修改的数据。
影响
如果,这时候事务2并不提交数据,而是回滚了数据,则此时的读取的数据就是脏数据.
解决方案
使用read commited级别,如果事务2的修改没有commit,则事务1读取的还是原数据.
可重复读测试
可重复读的级别对应的是read committed级别.也就是“读已提交”,主要是在事务1中查询数据时,此时事务1未提交,事务2修改了某项数据,并提交。此时事务1再次查询,就会出现数据不一致的现象。
- 开启两个mysql会话。
- 设置mysql会话隔离级别为read committed,并开启事务.
SET SESSION TRANSACTION ISOLATION LEVEL read committed; #设置为"读 未提交"级别
set autocommit = 0;
3.在事务1中查询数据.不commit;
4.在事务2中修改数据,并commit;
5.在事务1中再次查询数据,两次数据不一致.
影响
重复读取数据不一致
解决方案
提高到repeatable read(可重复读)隔离级别。
幻读测试
主要是在事务1操作时,事务2插入了一条数据,造成数据不一致.
- 开启两个mysql会话。
- 设置mysql会话隔离级别为repeatable read及其以下的级别,并开启事务.
SET SESSION TRANSACTION ISOLATION LEVEL repeatable read; #设置为"可重复读"级别
set autocommit = 0;
- 事务1中查询所有数据。
- 事务2插入一条数据,并提交.
- 事务1查询数据,发现不一致,多了一条,此时事务1并未提交.
影响
数据查询造成不一致
解决方案
设置隔离级别为serializable.
serializable,序列化
serializable可以解决幻读问题,事务1在查询过程中(未提交),此时在事务2中插入数据会进行等待.事务1提交后,如果事务2未提交,则事务1进行等待。以保证数据一致性.
总结
隔离级别越大,数据就越发安全,但是并发就越低下。在现实业务中,需要权衡利弊。
另外mysql默认级别是可重复读,默认不会造成脏读和可重复读问题。