Mysql事务特性、隔离特性的实现方法

一、 关系型数据库的ACID特性

  1. 原子性(Atomicity):事务是最小的执行单位,不允许分割。原子性确保要么执行完整的动作,要么就什么都不做。
  2. 一致性(Consistency):执行事务前后数据应该保持一致,例如转账业务中,无论事务是否成功,双方总额应当不变。
  3. 隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,且各并发事务之间数据库是独立的。
  4. 持久性(Durability):一个事务被提交之后,它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有影响。
  • ACID之间的关系
    只有保证了事务的持久性、原子性和隔离性,才能保证一致性。即A、I、D是手段,C是目的。
    原子性、隔离性和持久性是数据库的属性,而一致性是应用程序的属性。

二、 并发事务带来的问题

  1. 脏读(Dirty read)
    一个事务执行修改数据但是在提交之前进行数据回滚(也就是什么都没改),而另外一个事务在数据回滚之前读取了这个数据,即读到了第一步修改过的数据,这个数据即为脏数据。
  2. 丢失修改(Lost to modify)
    一个事务对某一数据进行修改后,另一个事务也进行了同样的修改,这样第一个事务内的修改结果就丢失了,此为丢失修改。
  3. 不可重复读(Unrepeatable read)
    指在一个事务内多次读同一数据。事务A两次读取同一数据之间事务B对数据进行修改,则事务A两次读取的值不同。
  4. 幻读(Phantom read)
    一个事务读取了几行数据,另一个事务插入了几行数据,第一个事务再次查询时就会发现一些原本不存在的记录,此为幻读。

三、SQL标准定义的事务隔离级别

  1. 读取未提交(Read-Uncommitted):最低的隔离级别,允许读取尚未提交的数据变更,可能导致脏读、幻读或不可重复读。
  2. 读取已提交(Read-Commited):允许读取并发事务已经提交的数据,可以阻止脏读,但不可避免幻读和不可重复读。
  3. 可重复读(Repeatable-Read):对同一字段的多次读取结果一致,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,幻读仍有可能。
  4. 可串行化(Serializable):最高的隔离级别,完全服从ACID隔离级别。所有的事务依次逐个执行,事务之间完全不会产生干扰。

四、 MySQL隔离级别的实现方法

MySQL的隔离级别基于锁和MVCC机制(多版本并发控制)共同实现。

4.1 MVCC技术(包含版本链、undo日志和Read View)

  • 版本链:数据表中的每行数据除了肉眼可见的数据还有几个隐藏字段,如下所述
    db_trx_id:最近修改/插入此行数据的事务ID:记录/创建这条记录最后一次修改该记录的事务ID;
    db_roll_ptr:回滚指针,指向这条记录的上一个版本(存储于rollback segment里);
    db_row_id:隐式主键,若数据表没有自定义主键,InnoDB会以db_row_id产生一个聚簇索引;
    delete_bit:删除标志,记录数据被更新或删除(并不是真的删除,而是改变删除标志)
  • undo日志:每次对数据库记录进行改动都会生成一条undo日志,每条undo日志也有一个roll_ptr属性,可以将此条数据对应的所有undo日志串成一个链表,表示这条记录的版本链。
    在这里插入图片描述

对该条记录每次进行更新后,都会将旧值放到一条undo日志中,视为该记录的一个旧版本,所有的版本形成一个链表(版本链),版本链的头节点就是当前记录最新的值,另外,每个版本中还包含生成该版本时对应的事务id。

  • Read View(读视图)
    事务进行快照读操作的时候产生读视图,在该事务执行快照读的一刻,会生成数据库系统当前的一个快照。读视图记录并维护系统当前活跃事务的ID列表,表示系统中当前不应该被本事务看到的其他事务ID列表。
    读视图主要用于做可见性判断,即某个事务执行快照读的时候,对该记录创建一个读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo日志中某个版本的数据。

4.2 RU(脏读、不可重复读、幻读都无法避免)

  • 所有的读操作不加锁,读到的数据都是最新的数据;
  • 所有的写操作加行级锁,写完释放。

4.3 RC(不可重复读和幻读无法避免)和RR(无法避免幻读)

  • RC隔离级别
    读操作:不加锁,每个快照读都会生成并获取最新的Read View,在读取时如果该行数据被其他事务占用,则通过版本链和Read View找到上一个有效的历史记录。
    写操作:加行级锁。事务执行后,会在undo日志中写入修改记录,更新版本链。

  • RR隔离级别
    读操作:不加锁,同一个事务中第一个快照读才会创建Read View,即之后快照读获取的都是同一个Read View,故可以避免重复读。
    写操作:同RC。

4.4 串行化:读和写都加锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值