脏写/空回滚/业务悬挂/隔离级别/脏读/(不)可重复读/幻读/多版本并发控制(MVCC)/next-key锁
~脏写
多线程并发访问AT模式的分布式事务时,事务a事务协调者(TC)在通知结果之前(提交or回滚),事务b对数据进行了操作,事务a根据快照恢复数据,就会丢失一次操作;
全局锁解决;
~空回滚
TCC模式的分布式事务中,
某事务分支try阶段阻塞导致全局事务超时而触发cancel操作,在未执行try操作的情况下执行了cancel,此时不能回滚,即空回滚;
判断try是否已经执行;
~业务悬挂
TCC模式的分布式事务中,空回滚之后,try操作恢复,永远不会执行confirm或cancel
事务一直处于中间状态,即业务悬挂;
记录事务状态解决;
~事务的隔离级别
读未提交:
所有事务都能读到其他事务未提交的数据,产生脏读问题;
~脏读:事务a修改数据未提交,事务b读取,事务a再次修改或者撤销修改,则事务b读取的是无效数据;
读已提交:
一个事务只能看见其他事务已提交的数据,避免了脏读,随之而来不可重复读,幻读;
~不可重复读:同一事务的两次读操作间其他事物修改了数据,导致两次读取数据不一致;
~幻读:事务b以插入或删除操作修改事务a的结果集;
可重复读:
确保一个事务中多个实例并发读取数据时有相同结果;
幻读问题仍然存在;
可串行化:
强制事务排序,数据行上加共享锁;
可解决幻读,但性能低;
那么;
幻读问题怎么有效解决?
~多版本并发控制(MVCC)快照读 select
InnoDB为例,每行加冗余字段(创建版本和过期版本),版本号随每次事务的开启自增;
事务每次取数据取创建版本小于当前事务版本和过期版本大于当前事务版本的数据;
原理:快照历史数据,其他事务操作对当前事务不可见;
~next-key锁(当前读)
包含行锁和间隙锁两部分;
行锁加在索引,间隙锁加在索引之间;
原理:将当前数据行与上一条数据和下一条数据之间的间隙锁定,保证此范围内读取的数据是一致的;
MySQL InnoDB引擎RR(可重复读)隔离级别是否解决了幻读?