mysql undo.log / redo.log
在MySQL数据库中,事务的持久性和恢复能力依赖于两个关键的日志系统:undo log 和 redo log。这两个日志系统协同工作,确保了数据库在发生故障时的数据完整性和一致性。
1. Undo Log (操作前的记录)
Undo Log 主要用于支持事务的原子性和持久性。当一个事务对数据库中的数据进行修改(例如,插入、更新或删除)时,MySQL会将这些修改前的数据版本记录在undo log中。这样,当事务需要回滚时,可以通过undo log中的记录来撤销这些修改,恢复到事务开始之前的状态。
Undo Log 的作用:
-
事务回滚:当事务执行失败或用户决定回滚时,可以使用undo log来撤销之前的操作。
-
多版本并发控制(MVCC):在InnoDB存储引擎中,undo log是实现MVCC的关键部分。它允许读取操作不会阻塞写操作,反之亦然。
2. Redo Log(操作后的)
Redo Log 主要用于支持事务的持久性。当事务对数据库进行修改时,这些修改首先会被写入到redo log中。然后,这些修改才会被应用到数据库的数据页中。这样做的目的是确保即使在系统崩溃的情况下,也能通过redo log中的记录来恢复数据页的修改,保证数据的持久性。
Redo Log 的作用:
-
数据恢复:在系统崩溃或宕机后,可以通过redo log中的记录来重做(redo)那些尚未应用到数据文件中的事务操作,从而恢复数据库的一致性状态。
-
提高性能:通过减少对数据文件的直接写入操作(先写redo log),可以减少I/O操作的次数,提高数据库的写入性能。
两者之间的关系和重要性
-
事务提交:一个事务在提交前,其所有的修改首先被写入redo log,然后才被写入数据库的数据页。这样即使系统崩溃,也可以通过redo log来恢复数据页的修改。
-
事务回滚:如果事务需要回滚,则通过undo log来撤销之前对数据的修改。
数据记录的隐藏字段
mysql在建表时,不仅仅创建了表的结构,还创建了3个隐藏字段。
DB_TRX_ID :6 byte,最近修改( 修改/插入 )事务ID,记录创建这条记录/最后一次修改该记录的事务ID
DB_ROLL_PTR : 7 byte,回滚指针,指向这条记录的上一个版本(简单理解成,指向历史版本就 行,这些数据一般在 undo log 中)
DB_ROW_ID : 6 byte,隐含的自增ID(隐藏主键),如果数据表没有主键, InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引
聚簇索引和普通索引
聚簇索引整体是一个B+树,非叶子节点存放的是键值,叶子节点存放的是行数据,称之为数据页,这就决定了表中的数据也是聚簇索引中的一部分,数据页之间是通过一个双向链表来链接
普通索引:也叫二级索引,辅助索引, 除聚簇索引外的索引,即非聚簇索引。
所以普通索引查询记录的时候,如下
select id,name from user where age = 10;
1. 首先通过普通索引(age) 定位 age = 10 的ID
2. 然后通过聚集索引 查询select 字段返回结果集
即此过程 需要扫描两次索引B+树,它的性能较扫一遍索引树更低
数据版本链
两个事务的操作
事务1: 对student表中记录进行修改(update):将name(张三)改成name(李四)
事务2: 对student表中记录进行修改(update):将age(28)改成age(38)
隔离级别与ReadView
隔离级别可以复习: MySQL 四种隔离级别及测试_mysql隔离级别测试-优快云博客
ReadView
仅仅适用于读已提交
和可重复读
隔离级别, 对于这两种隔离级别, 都必须保证读到的是已经提交的事务修改过的记录. 假如另一个事务已经修改但是还没有提交, 是不能直接读取到的. 核心问题是判断版本链中哪些版本记录是当前事务可见的
如何解决,显然需要将事务进行分类,已完成的、进行中的要保存;且要保存一个一个视图
- creator_trx_id: 创建这个ReadView的事务ID.
- trx_ids: 在生成ReadView时, 当前系统中活跃的读写事务的ID列表.
- up_limit_id: 活跃的事务中最小的事务ID.
- low_limit_id: 表示在生成ReadView时系统应该分配给下一个事务的ID, 也就是系统中最大的事务ID值.
如下:事务2读取时,事务4已经提交了事务
//事务2的
Read View m_ids; // 1,3
up_limit_id; // 1
low_limit_id; // 4 + 1 = 5,ReadView生成时刻,系统尚未分配的下一个事务ID
creator_trx_id // 2
事务2能读到的最新数据记录是事务4所提交的版本,而事务4提交的版本也是全局角度上最新的版本
回到mvcc概念
MVCC也称: 多版本并发控制. 顾名思义, MVCC是通过数据行的多个版本管理来实现数据库的并发控制. MVCC使得在InnoDB的事务隔离级别下, 执行一致性读操作有了保证. 简单来说就是: 在需要读取一些正在被另一个事务更新的行数据时, 读取之前的历史版本数据(旧数据); 而不需要等待另一个事务释放锁.
MySQL的MVCC(多版本并发控制)机制主要解决了读写并发冲突问题,实现了读操作不阻塞写操作、写操作不阻塞读操作,从而提高了数据库的并发性能。
隔离级别 | mvcc的行为差异 |
读已提交(Read committed) | 每次读都生成ReadView,可以读取到其它事务已提交的修改 |
可重复读(Repeatable read(MySQL默认)) | 事务首次生成ReadView,后续复用,保证读取的一致性 |