MySQL-事务

MySQL 事务的四大特性说⼀下?

在这里插入图片描述

  • 原⼦性:事务作为⼀个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • ⼀致性:指在事务开始之前和事务结束以后,数据不会被破坏,假如 A 账户给 B 账户转 10 块钱,不管成功与否,A 和 B 的总⾦额是不变的。
  • 隔离性:多个事务并发访问时,事务之间是相互隔离的,即⼀个事务不影响其它事务运⾏效果。简而⾔之,就是事务之间是进⽔不犯河⽔的。
  • 持久性:表⽰事务完成以后,该事务对数据库所作的操作更改,将持久地保存在数据库之中。

那 ACID 靠什么保证的呢?

  • 事务的隔离性是通过数据库锁的机制实现的。
  • 事务的⼀致性由 undo log 来保证:undo log 是逻辑⽇志,记录了事务的 insert、update、deltete 操作,回滚的时候做相反的 delete、update、insert 操作来恢复数据。
  • 事务的原⼦性和持久性由 redo log 来保证:redolog 被称作重做⽇志,是物理⽇志,事务提交的时候,必须先将事务的所有⽇志写⼊ redo log 持久化,到事务的提交操作才算完成。
    在这里插入图片描述

事务的隔离级别有哪些?MySQL 的默认隔离级别是什么?

在这里插入图片描述

  • MySQL 默认的事务隔离级别是可重复读 (Repeatable Read)。

事务的各个隔离级别都是如何实现的?

  • 读未提交,就不⽤多说了,采取的是读不加锁原理。
    • 事务读不加锁,不阻塞其他事务的读和写
    • 事务写阻塞其他事务写,但不阻塞其他事务读;
  • 读取已提交&可重复读
  • 读取已提交和可重复读级别利⽤了 ReadView 和 MVCC ,也就是每个事务只能读取它能看到的版本(ReadView)。
    • READ COMMITTED:每次读取数据前都⽣成⼀个 ReadView
    • REPEATABLE READ :在第⼀次读取数据时⽣成⼀个 ReadView。repeatable
  • 串行化:串⾏化的实现采⽤的是读写都加锁的原理。

什么是幻读,脏读,不可重复读呢?

  • 事务 A、B 交替执⾏,事务 A 读取到事务 B 未提交的数据,这就是脏读。
  • 在⼀个事务范围内,两个相同的查询,读取同⼀条记录,却返回了不同的数据,这就是不可重复读。
  • 事务 A 查询⼀个范围的结果集,另⼀个并发事务 B 往这个范围中插⼊ / 删除了数据,并静悄悄地提交,然后事务 A 再次查询相同的范围,两次读取得到的结果集不⼀样了,这就是幻读。
  • 不同级别下,并发事务可能发生的问题:
    在这里插入图片描述

MVCC 了解吗?怎么实现的?

  • 中⽂名是多版本并发控制,简单来说就是通过维护数
    据历史版本,从而解决并发访问情况下的读⼀致性问题。关于它的实现,要抓住几个关键点,隐式字段、undo ⽇志、版本链、快照读&当前读、Read View。

版本链

  • 对于 InnoDB 存储引擎,每⼀⾏记录都有两个隐藏列DB_TRX_ID、DB_ROLL_PTR
  • DB_TRX_ID ,事务 ID,每次修改时,都会把该事务 ID 复制给 DB_TRX_ID ;
  • DB_ROLL_PTR ,回滚指针,指向回滚段的 undo ⽇志。
    在这里插入图片描述
    假如有⼀张 user 表,表中只有⼀⾏记录,当时插⼊的事务 id 为 80。此时,该条记录的⽰例图如下:
    在这里插入图片描述
    接下来有两个 DB_TRX_ID 分别为 100 、 200 的事务对这条记录进⾏ update 操作,整个过程如下:
    在这里插入图片描述
    由于每次变动都会先把 undo ⽇志记录下来,并用DB_ROLL_PTR 指向 undo ⽇志地址。因此可以认为,对该条记录的修改⽇志串联起来就形成了⼀个 版本链 ,版本链的头节点就是当前记录最新的值。
    如下:
    在这里插入图片描述

ReadView

对于 Read Committed 和 Repeatable Read 隔离级别来说,都需要读取已经提交的事务所修改的记录,也就是说如果版本链中某个版本的修改没有提交,那么该版本的记录时不能被读取的。所以需要确定在 Read Committed 和 Repeatable Read 隔离级别下,版本链中哪个版本是能被当前事务读取的。于是就引⼊了 ReadView 这个概念来解决这个问题。

在这里插入图片描述

Read View 就是事务执⾏快照读时,产⽣的读视图,相当于某时刻表记录的⼀个快照,通过这个快照,我们可以获取:

  • m_ids :表⽰在⽣成 ReadView 时当前系统中活跃的读写事务的事务 id 列表。
  • min_trx_id :表⽰在⽣成 ReadView 时当前系统中活跃的读写事务中最⼩的 事务 id ,也就是m_ids 中的最⼩值。
  • max_trx_id :表⽰⽣成 ReadView 时系统中应该分配给下⼀个事务的 id 值。
  • creator_trx_id :表⽰⽣成该 ReadView 的事务的 事务 id
    有了这个 ReadView ,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见:
  • 如果被访问版本的 DB_TRX_ID 属性值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它⾃⼰修改过的记录,所以该版本可以被当前事务访问。
  • 如果被访问版本的 DB_TRX_ID 属性值⼩于 ReadView 中的 min_trx_id 值,表明⽣成该版本的事务在当前事务⽣成 ReadView 前已经提交,所以该版本可以被当前事务访问。
  • 如果被访问版本的 DB_TRX_ID 属性值⼤于 ReadView 中的 max_trx_id 值,表明⽣成该版本的事务在当前事务⽣成 ReadView 后才开启,所以该版本不可以被当前事务访问。
  • 如果被访问版本的 DB_TRX_ID 属性值在 ReadView 的 min_trx_id 和 max_trx_id 之间,那就需要判断⼀下 trx_id 属性值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时⽣成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时⽣成该版本的事务已经被提交,该版本可以被访问。

如果某个版本的数据对当前事务不可见的话,那就顺着版本链找到下⼀个版本的数据,继续按照上边的步骤判断可见性,依此类推,直到版本链中的最后⼀个版本。如果最后⼀个版本也不可见的话,那么就意味着该条记录对该事务完全不可见,查询结果就不包含该记录。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值