探秘MySQL——全面了解事务及其底层实现(undo log、redo log、binlog、锁、MVCC)

〇、基本概念

什么是事务

  • 定义:

事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。

  • ACID特性:
    原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
    一致性:事务前后数据的完整性必须保持一致。
    隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
    持久性:一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

事务的 具体实现内容 在下文进行更为详细的介绍。

Q.Jdbc同一个事务中,一个ip地址对应多个连接的操作,在事务中会生效吗?

  • JDBC中的事务机制:
    当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
    关闭数据库连接,数据就会自动的提交。
    同一个事务的多个操作必须在同一个连接下:如果多个操作分别使用的是自己单独的连接,则无法保证事务。

一、MySQL日志

鉴于后文与日志息息相关,因此单独整理一个章节来介绍MySQL中三种重要的日志。

1.redo log(重做日志)

MySQL的Redo Log(重做日志)是一种用于持久化事务操作的机制,它记录了对数据库进行的修改操作,以确保数据的持久性和一致性。Redo Log的底层原理如下:

  1. Redo Log的结构:Redo Log是一个循环的、固定大小的日志文件,通常由多个物理文件组成。每个物理文件称为一个Redo Log组成员(Log Group Member),每个组成员都有一个唯一的标识符。

  2. Redo Log的写入过程:当事务执行修改操作时,MySQL首先将修改操作记录到内存中的Redo Log缓冲区(Redo Log Buffer)。Redo Log Buffer是一个内存区域,用于临时存储待写入Redo Log文件的日志记录。

  3. Redo Log的刷写过程:为了保证数据的持久性,MySQL会定期将Redo Log Buffer中的日志记录刷写(Flush)到磁盘上的Redo Log文件中。这个过程称为Redo Log的刷写。

  4. Redo Log的重做过程:当数据库发生崩溃或意外关闭时,MySQL可以通过Redo Log来恢复数据的一致性。在数据库重启时,MySQL会根据Redo Log文件中的日志记录,重新执行未完成的事务操作,将数据恢复到崩溃前的状态。

需要注意的是,Redo Log是顺序写入的,这使得它具有高性能和低延迟的特点。通过将修改操作记录到Redo Log中,MySQL可以将磁盘随机写入操作转换为顺序写入操作,从而提高写入性能。

此外,MySQL还使用了一种叫做Checkpoints的机制来优化Redo Log的刷写过程。Checkpoints是一种定期将内存中的数据刷写到磁盘的操作,它可以减少数据库崩溃时的恢复时间。

2.undo log(回滚日志)

MySQL的Undo Log(回滚日志)是一种用于实现事务的回滚和MVCC(多版本并发控制)机制的日志。它记录了对数据库进行的修改操作的逆操作,以便在事务回滚或读取旧版本数据时使用。Undo Log的底层原理如下:

  1. Undo Log的结构:Undo Log是一个逻辑日志,它以事务为单位进行记录。每个事务都有一个对应的Undo Log,其中包含了该事务所做的修改操作的逆操作。

  2. Undo Log的写入过程:当事务执行修改操作时,MySQL首先将修改前的数据记录到Undo Log中。这样,在事务回滚时,可以通过Undo Log将数据恢复到事务开始之前的状态。

  3. Undo Log的回滚过程:当事务需要回滚时,MySQL会根据Undo Log中的逆操作,将数据恢复到事务开始之前的状态。通过逆向执行Undo Log中的操作,可以撤销事务所做的修改。

  4. Undo Log的读取过程:在MVCC机制中,当一个事务读取数据时,MySQL会根据事务的隔离级别和数据的版本号来决定读取哪个版本的数据。如果需要读取旧版本的数据,MySQL会通过Undo Log来获取旧版本的数据。

需要注意的是,Undo Log的数据是存储在磁盘上的,而不是存储在内存中。这使得Undo Log可以支持大量的并发事务和大量的修改操作。

Undo Log在MySQL中的作用非常重要,它不仅用于事务的回滚和数据的恢复,还支持MVCC机制,提供了高并发的读写操作。

Q.同一个事物内的一条记录被多次修改,每次数据修改前的状态都会写入undo log吗?

undo log只负责记录事务开始前要修改数据的原始版本。

3.bin log(二进制归档日志)

  • 非擦除:
    bin log记录了数据库所有修改操作,它不会像redo log那样循环写擦除之前的记录,而是会一直记录日志。一个bin log日志文件默认最大容量1G,单个日志超过最大值,则会新创建一个文件继续写日志。

  • 记录反向逻辑:
    和undo log类似,bin log记录的是执行SQL命令的反向逻辑,另外,bin log日志文件需要设置过期时间。

  • 作用:
    用处一:主从模式中主从节点间的数据同步;
    用处二:数据还原。

bin log是人工使用(数据恢复、主从复制和增量备份等场景),redo log、undo log是事务使用。

二、原子性实现

undo log: 当一个事务需要回滚时,MySQL会使用undo log将修改的数据恢复到原始状态。

三、持久性实现

redo log: 事务持久化。

bin log: 数据库持久化。

四、隔离性实现

MySQL的事务隔离性是通过 上锁+MVCC 实现的。

1.并发事务带来的问题

  • 脏读: 读取到了其他事务修改了但还没提交的数据。
  • 不可重复读: 在同一个事务中,两次读取的数据不同,因为在此期间被其他事务修改了。
  • 幻读: 在同一个事务中,两次读取的数据行数不同,因为在此期间事务新增/删除了记录。

2.标准SQL事务隔离级别

MySQL事务隔离级别 默认是可重复读。

在这里插入图片描述

3.MySQL锁

  • 全局锁: 对整个数据库实例加锁,将进入全局只读状态。
  • 表锁: 对一张表加锁。
  • 行锁: 对符合条件的索引项加锁。
  • 间隙锁: 对一个行范围加锁,在这个范围内不能插入记录,但是不锁定行本身。即,可删除、不可插入。解决了插入幻读 问题。
  • 行锁+间隙锁: 范围内,不可删除、不可插入。解决了插入幻读、删除幻读 问题。

4.事务隔离性实现(锁+MVCC)

MySQL 提前一级 解决并发读写问题。

  • 读未提交: 读不加锁,更新加行级共享锁。有 脏读 问题。
  • 读提交(提前一级): 读不加锁为MVCC快照读,更新加行级排它锁。解决 脏读、不可重复读 问题。
  • 可重复读(提前一级): 读不加锁为MVCC快照读,更新加行级排它锁+间隙锁。解决脏读、不可重复读、幻读 问题。
  • 序列化: 读加表级共享锁,更新加表级排它锁。
快照读: InnoDB 通过 MVCC(多版本控制)将数据库在过去某个时刻的快照应用在查询上,使得:
这次查询 只能看到 别的事务生成快照前提交的数据,而不能看到 别的事务生成快照后提交的数据或者未提交的数据。

Q.针对幻读,事务1插入,不提交,事务2,插入前,事务2查询,插入后,再查询,会发生什么情况?

MySQL默认事务隔离级别是可重复读,在这一隔离级别,已经基于锁+MVCC解决了幻读问题,因此 不会出现幻读现象

具体: 事务1插入前事务2读到的是没有插入的数据(并且是快照读),事务1插入后,事务1 会生成新的快照,但是事务2读的还是自己之前读的那个快照,并不是这个事务1新产生的快照。

特殊情况: 在一些特殊情况下,仍然可能会发生幻读。例如,如果事务1在执行完插入操作后,立即提交并释放锁,而事务2在执行查询操作时,会重新获取锁并读取最新的数据快照版本。这种情况下,事务2就有可能发生幻读现象,因为它读取的数据快照版本已经更新,包含了事务1插入的新数据。

Q.死锁问题的产生和解决

两阶段锁协议: InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,需要等事务结束时才释放,这就是两阶段锁协议。遵循此协议可能带来事务 死锁 问题。

在这里插入图片描述

解决: ①超时等待之后事务退出;②设置死锁检测,发现死锁之后主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。

参考

事务实现
日志

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MySQL中的Redo LogBinlogUndo Log是三种不同的日志类型,用于支持数据库事务的持久性、复制和回滚操作。 1. Redo Log(重做日志): Redo LogMySQL引擎内部使用的一种日志,记录了所有已提交的修改操作,以保证数据库在发生崩溃等异常情况下能够进行恢复。当数据库发生崩溃时,可以通过Redo Log来重放这些修改操作,使数据库恢复到崩溃前的状态。Redo Log是在InnoDB存储引擎中实现的,通常以磁盘文件形式存在,可被视为一种类似于事务日志的机制。 2. Binlog(二进制日志): BinlogMySQL数据库服务器层产生的一种日志,用于记录数据库中所有的修改操作,包括数据修改和数据定义语句(DDL)。与Redo Log不同,Binlog记录的是逻辑操作而不是物理操作,以提供对数据的逻辑复制和恢复能力。Binlog通常以二进制文件的形式存在,并且可以被用于主从复制和数据恢复等任务。 3. Undo Log(回滚日志): Undo Log是用于支持事务回滚操作的一种日志。当一个事务执行修改操作时,旧值会被记录在Undo Log中,以便于回滚操作时能够恢复到之前的状态。Undo Log通常与事务的隔离级别和并发控制有关,主要用于MVCC(多版本并发控制)的实现。 这三种日志在MySQL中扮演了不同角色,分别用于保证数据的持久性、支持复制和提供事务回滚功能。在数据库的正常运行和异常恢复中起到至关重要的作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracyCoder123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值