三种事务bug问题理解
脏读:读到其他事务未提交的数据;
不可重复读:事务内,相同的where条件,select/update/delete查询结果不一致;
幻读:事务内,相同的where条件,insert导致的查询结果不一致;
更新丢失:
mysql的mvcc解决方案
rc级别-读提交:
redo.log保证只有事务提交后,修改结果才可见,解决脏读;
针对当前读,RC隔离级别保证对读取到的记录加锁 (行锁),存在幻读现象;
select/update/delete/insert都是当前读,读结果可能不一致,存在不可重复读问题;
rr级别-可重复读:
针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象;
针对快照读,普通select并不会加锁,因此select和update读的结果也可能不一致!也存在不可重复读问题;
Serializable级别 从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)
基于锁的并发控制,Lock-Based Concurrency Control
vs 不可重复读,rc隔离级别已经解决脏读问题,试图解决不可重复读问题;for update 锁定当前读,属于精准匹配锁定,锁定行不可修改,但不能解决幻读问题;
vs 幻读,rr隔离级别,试图解决幻读问题,for update锁定索引行+gap锁,可以解决幻读问题;
理解快照读和当前读
rr不带锁的查询(select)读快照,rc不带锁读当前;
(select for update/update/delete)带锁的查询读最新(读当前)
理解rc和rr的差异
rc下的锁,锁定精确匹配行;rr下的锁,锁定索引+gap锁,锁定的范围广且重,有时候这并不一定是想要;
rc下的读快照,每次都读最新的ReadView,也就是最新已事务提交的数据,因此不可重复读;rr下的读快照是可重复读,重复第一条select读时生成ReadView,因此可重复读;
思考,虽然可重复读,但是
A1
select * from user where id=1;
-- effect 0 不存在id=1的记录
A2
update set age=18 where id=1;
B1
update set age=19 where id=1;
-- rr模式下,id=1被锁定,B1被阻塞;rc模式下,不存在匹配行,B1不会被阻塞;
A3
commit
最佳实践
只要锁多行,就有可能发生死锁,但是只要保证锁定表顺序是一致的就可以避免死锁;
顺上,锁定表内有不同行的锁定,也是容易发生死锁的;
rc+强制读当前+锁,可重复读;
rr+强制读当前+锁,完全避免幻读;
因地制宜;
共享锁
思考
rr下,可重复读是指两次select快照读,其他都是读当前,快照读是不准确的,有啥用呢?。
参考:https://www.cnblogs.com/crazylqy/p/7611069.html
最后编辑于 :2020.07.02 15:12:23
©著作权归作者所有,转载或内容合作请联系作者 平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。