今天看了Spring声明式事务,回看了之前相关的MySQL笔记,有了更体系化的认识,现在整理下。
2、概念锁方面的概念:MyISAM 与 InnoDB 关于锁方面的区别更新丢失、脏读、不可重复读、幻读:数据库操作会产生的一致性问题ACID:是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性
原子性(atomicity,或称不可分割性)一致性(consistency)隔离性(isolation,又称独立性)持久性(durability) 事务隔离级别的概念:来源于ACID中I的应用,用于解决C的问题,事务隔离级别与一致性问题的关系 3、整体性认识
【更新丢失、脏读、不可重复读、幻读】是并发操作产生的数据不一致隐患,可能会产生业务逻辑上的bug。【事务隔离级别】是数据库针对解决【更新丢失、脏读、不可重复读、幻读】的方案,这些方案背后是一系列的算法支持。事务隔离级别直接体现整体并发度。隔离级别越高,则并发度越低。
在数据一致性和并发度的追求上,我们往往有所折中,并不会采用SERIALIZABLE牺牲所有并发度,也不会采用READ-UNCOMMITTED暴露所有一致性隐患。那么留下来的选择就是READ-COMMITTED和REPEATABLE-READ,也就是常说的RC和RR的隔离级别。我个人觉得使用这两个隔离级别没有绝对的对错,需要根据业务场景进行综合考量。庆幸的是,我们可以暂时把只把目光放在RC和RR的隔离级别上。
4、实践意义考虑什么情况下使用RC或RR的隔离级,也就成为指导实践的线索。
4.1 RR隔离级别RR级别下唯一存在的隐患就是幻读,如果能够解决幻读问题,意味着程序能够兼顾并发度和数据一致性。InnoDB 如何防止幻读。
幻读隐患的触发条件 当前读和快照读混用不同事务的更新并发操作 消除幻读隐患可能会产生的弊端
RR下解决幻读,虽然增加了并发度也保障了数据一致性,但是容易产生死锁的可能性(TODO 这个内容比较深,目前还在了解的阶段)
4.2 RC隔离级别幻读产生的条件是严格的,而且业务逻辑上可能是被允许的。比如A事务插入了新记录A,B事务需要范围更新一批记录,刚好这个范围又包括新纪录A,那么这个更新操作虽然属于幻读,但是也应该再业务上合法。
RC级别下的并发度比RR高,则在另一方面,对SQL语句的书写规范有着更高的要求。值得一提的是,该级别下一定会出现幻读的隐患,如果业务上对幻读的发生是不在意的,那么可以考虑使用该级别。该级别下急切要解决的是可重复读的隐患。
可重复读隐患的触发条件
业务逻辑里面读取同一条记录两遍,使用ORM的情况下,是很少单独查一个表查两遍的。但是如果出现了范围查询,很有可能会隐性得读同一条记录两遍消除幻读隐患可能会产生的弊端
需要了解到,RC无法消除可重复读的隐患。
4.3 总结不可重复读,读的数据都是已经提交过的数据,业务上如果一个事务需要反复确认最新的数据,不可重复读也许是一个优势。不同角度看问题,隐患也成为了一种优势。
如果不需要较高的并发度,使用RR隔离级别即可。如果需要较高的并发读,在RC级别下使用合理的编程习惯,也无大碍。关键得是程序员要在编程的时候,了解自己事务所处的隔离环境,不要轻易写出update insert后不命中索引的锁表的语句,也不要反复先select再update造成一致性的隐患。