1、脏读、不可重复读、幻读
设表 t(id PK, name);
表中有三条记录:
1, ermazi
2, zhangsan
3, lisi
1.1脏读
事务A,先执行,处于未提交的状态:
insert into t values(4, wangwu);
事务B,后执行,也未提交:
select * from t;
如果事务B能够读取到(4, wangwu)这条记录,事务A就对事务B产生了影响,这个影响叫做“读脏”,读到了未提交事务操作的记录。
2.2不可重复读
事务A,先执行:
select * from t where id=1 ;
结果集为:
1, ermazi
事务B,后执行,并且提交:
update t set name=xxoo where id=1;
commit;
事务A,再次执行相同的查询:
select * from t where id=1;
结果集为:
1, xxoo
这次是已提交事务B对事务A所访问的对应记录产生的影响,这个影响叫做“不可重复读”,一个事务内相同的查询,得到了不同的结果。
3.3幻读
事务A,先执行:
select * from t where id>3;
结果集为:
NULL
事务B,后执行,并且提交:
insert into t values(4, wangwu);
commit;
事务A,首次查询了id>3的结果为NULL,于是想插入一条为4的记录:
insert into t values(4, xxoo);
结果集为:
Error : duplicate key!
这次是已提交事务B对事务A的区间记录产生的影响,这个影响叫做“幻读”,对于innoDB来讲是因为在读提交(RC)隔离级别下未使用间隙锁。
2、四种隔离级别
四种隔离界别分别是(前两种不做讨论):
1. 读未提交(Read Uncommitted)——会产生脏读
2. 串行化(Serializable)——所有select语句都会被隐式的转化为select ... in update. 这可能导致,如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住
3. 可重复读(Repeated Read, RR)——普通select快照读,锁select /update /delete 根据查询条件情况,会选择记录锁,或者间隙锁/临键锁,以防止读取到幻影记录;
4. 读提交(Read Committed, RC)——普通select快照读,锁select /update /delete 会使用记录锁;