未提交读→已提交读→可重复读→串行
什么锁都不加时候,可能多个连接同时修改同个数据,会导致丢失修改,
说白了就是俩人都根据原数据去改一个数据, 一个人的数据把另外一个给覆盖了, 另一个就像根本没发生过更新.
这种事只会出现在想象中, 数据库不会允许这种事情
READ UNCOMMITED 未提交读
解决办法:排他锁(Exclusive Lock) , 写锁, 简称X锁,
一个人改,另一个人就不能改
问题:脏读
会读到未提交的脏数据,没准b读了以后 a又回滚了 ,
READ COMMITED (已提交读 )
解决办法:
a改的时候,b读都不能读,
专门用于共享数据的读取, 就叫共享锁(Share lock) 读锁,简称S锁,
但是,还有为了防止长时间的锁住, 不管我们要做的事情有多少, 读一个数据之前加S锁, 读完之后立刻释放读锁 ,而不是等到事务结束
innodb 实现: 每个sql 一个视图, 这时间前提交的可见,没提交的都不可见,同一个事务的不一定是一个视图, 可能查询结果不一致
问题:不可重复读
左边只读数据,没写数据,但是2次读到的B数据不一样
REPEATABLE READ (重复读)
解决:
读数据的时候, 也需要一直锁定了, 不再读完就释放读锁,要直到事务提交都不释放:
可重复读, 同个事务 读同样的记录 结果一致,即使第二次查一样的记录,
记录已经被另一个事务修改了 ,本事务也看不到
这是mysql默认级别,
实现方法是, 事务开始时的视图, 用undo log回退到可见的版本
但是 : a对全表操作,锁的是已有的行,b插入新行,资源上并不冲突,是可以的
问题:幻读,
session A 的更新操作范围内, session B 插入/删除了整行
如: 旺财对一个“学生表”进行操作,选取了年龄是18岁的所有行,一共5行, 用X锁(写锁)锁住, 并做了修改, 改成女的。
1.结果显示该了6行?(innodb在读已提交才会这样)
2.改完以后旺财再次选择所有年龄是18岁的行, 想做一个确认, 没想到有一行竟然没有修改!
原来就在旺财查询并修改的的时候, 小强也对学生表进行操作, 他插入了一个新的行也是18岁的!
实际上innodb不会幻读, 加了写锁以后,会阻塞另一个session的插入或者删除行,
SERIALIZABLE
解决:
串行执行,无并发 一般不这么干