- 事务隔离级别
-
隔离级别 数据一致性 脏读 不可重复读 幻读
Read uncommitted 不能 是 是 是
Read committed 语句级别一致 否 是 是
Repeated read 事务级别一致 否 否 是
Serializable 最高级别,事务级 否 否 否
并发事务带来问题
- 脏读:一个事务读取到另一个事务未提交的数据;
- Phantom Read幻读:在一个事务中,同样的sql被2次执行,得到不同的结果集。
- Non-repeatable Read不可重复读:在一个事务中,同样的数据被2次读取,得到不同的结果集
不可重复读的重点是:修改: 同样的条件, 你读取过的数据, 再次读取出来发现值不一样了
幻读的重点在于:新增或者删除同样的条件, 第1次和第2次读出来的记录数不一样
从锁的角度来看, 两者的区别就比较大:
对于前者, 只需要锁住满足条件的记录
对于后者, 要锁住满足条件及其相近的记录Innodb 幻读问题:
Innodb事务 默认是Repeated read,read是不加任何锁的,通过多版本控制来保障没有脏读, 不可重复读,数据一致性。 insert,update,modify加记录排他锁。解决幻读问题需要 使用next-lock。
record-lock:对索引项加锁
Gap-lock:间隙锁,锁定范围
next-lock:前两种的组合,对记录和间隙加锁。如果不加next-lock会出现的幻读问题:
一个事务中有两条search操作,另一个事务delete掉第一个事务search到的记录项,并commit,则第一个事务会出现两次search结果集不一致的情况。所以需要用:
`(共享锁):select * from table where … lock in shared mode;
(排他锁):select * from table where … for update`
`select * from table where key<value for update`
----会对索引小于value范围加锁。
`select * from table where key==value for update`
----会对索引项加锁。
select记录为空,会对max记录和小于它的范围加锁。
**这样另外一个事务就会等锁,不能insert或delete掉,所以避免幻读**
特例:
一个事务,select * from table where … for update没有记录,另一个search… for update也没有时,是不会锁住的,当时两个事务insert都会等锁。