事物隔离级别、MVCC以及数据库中常见锁介绍
事务的基本要素(ACID)
1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
其中原子性、持久性由 redo log (重做日志)来实现, undo log 用来保证事务的一致性。
并发环境下易出现的问题
1.丢失修改
T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。
2.读脏数据
T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。
3.不可重复读
T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
注意:不可重复读与脏读的区别,脏读读的是未提交的数据,不可重复读读的是已经提交的数据。
4.幻影读
T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低的隔离级别通常可以执行更高的并发,系统的开销也更低。
事务的隔离级别
1.未提交读(READ UNCOMMITTED)
事务中的修改,即使没有提交,对其它事务也是可见的,这就会导致脏读的发生。它是最低层次的隔离级别,并发情况下,容易出现大量并发问题,实际业务场景中几乎不会使用。
2.提交读(READ COMMITTED)
一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的,说到这,我们就能发现,这个级别就已经实现了上面我们所定义的事务的隔离性了!它能有效的解决脏读的问题,但是值得注意的是,假如一个事务T从开始到提交这一期间,可能有很多其他事务都已经提交了,如果这些其他的提交过的事务修改了事务T中所用到的数据,这就会导致不可重复读的问题发生。
3.可重复读(REPEATABLE READ)
保证在同一个事务中多次读取同样数据的结果是一样的。这解决了脏读的问题,也解决了不可重复读的问题。
但是请注意,可重复读隔离级别下,仅仅保证了对同样的数据的读取结果是一致的,但是对于范围读取,依然会存在幻影读的情况!
4.可串行化(SERIALIZABLE)
这是最暴力的手段,是一种悲观的并发策略,它会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题,但由于事务都串行化执行了,那么也没有并发问题了。实际应用中很少使用这个隔离级别,除非在那种非常需要保证数据一致性和可以接受没有并发的情况下,才会考虑采用这个隔离级别。
有一个事务隔离性的例子
为什么不要使用长事务
长事务意味着系统里面会存在很老的事务视图,由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间。
在MySQL 5.5 及以前的版本,回滚日志是跟数据字典一起放在 ibdata 文件里的,即使长事务最终提交,回滚段被清理,文件也不会变小,可能出现数据只有20GB,而回滚段有200GB 的库,最终只好为了清理回滚段,重新建个库。
除了对回滚段的影响,长事务还占用锁资源,也可能拖垮整个库
数据库各种锁
注意:Record Locks锁定一个记录上的索引,而不是记录本身。如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks 依然可以使用。
MVCC的一个例子
有的资料显示MVCC其实在每行末增加了三列,第三列其实是一个隐藏id,没有其他作用
参考链接:
【1】https://www.cnblogs.com/shihaiming/p/11044740.html
【2】CyC
【3】为什么不要使用长事务https://blog.csdn.net/xcy1193068639/article/details/85058641
【4】https://blog.csdn.net/u013568373/article/details/90550416