1.隔离等级产生的问题
脏读(Drity Read):A,B两个事务同时操作表C,A事务修改C表但是未提交,但是此时B事务查询会获取到A事务修改后的数据。
不可重复读(Non-repeatable read):A,B两个事务同时操作表C成绩字段,A事务第一次查询成绩为80(A事务未结束),B事务修改成绩为90分,此时A事务再次查询成绩就为90分。两次查询结果不同。
幻读(Phantom Read):A,B两个事务操作C表,A查询id为100分的数据,得到null,此时B插入一条id为100数据,提交,A再次插入id为100的数据发现数据已经存在,A懵逼了,刚才我还没有查到为什么不能插入。。。。。。
2.事务的隔离等级
未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据。
提交读(Read Committed):只能读取到已经提交的数据。
可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读。
串行化(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞,效率最低,可以避免脏读,幻读,不可重复读。
这四种隔离等级从上向下依次变低
脏读 | 不可重复读 | 幻读 | |
未提交读 | √ | √ | √ |
提交读 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
3.避免幻读的方法
在第一次查询之后,手动加入锁,不允许别人插入id为100的数据。
SELECT id FROM C WHERE id = 100 FOR UPDATE;
4.数据库默认的隔离等级
mysql默认的隔离等级 可重复读。
oracle,SQL Server默认为 提交读。
5.查询mysql当前隔离等级
1. 1.查询当前会话和全局会话等级 2. SELECT @@global.tx_isolation, @@tx_isolation; 3. 4. 2.设置当前会话隔离级别 5. 6. set session transaction isolatin level (read uncommitted,read committed,repeatable read,serializable); 7. 8. 3.设置系统当前隔离级别 9. 10. set global transaction isolation level (read uncommitted,read committed,repeatable read,serializable);