当前位置: 首页 > news >正文

MySQL常用知识总结

MyISAM和InnoDB的区别

MyISAM

  • 不支持事务
  • 仅支持 ​​表级锁​​,执行写操作时会锁住整个表,读写互斥,并发性能较差(适合读多写少场景)。
  • 不支持外键​
  • 无崩溃恢复机制,意外断电或崩溃可能导致表损坏,需手动修复(如 REPAIR TABLE)。
  • MyISAM存储引擎数据和索引文件是分开

InnoDB

  • 支持 ​​ACID 事务​​(原子性、一致性、隔离性、持久性)
  • 支持 ​​行级锁​​(默认)和表级锁,写操作仅锁定相关行,允许多行并发修改,适合高并发写入场景。
  • 支持 ​​外键​​,但是开发中也不会使用外键
  • 通过 ​​事务日志(redo log)​​ 实现崩溃恢复,即使数据库异常终止,也能通过日志重放保证数据一致性。
  • 支持MVCC(多版本并发)
  • 特定情况下的索引和数据都在同一个文件上,也就是我们常说的聚簇索引,通过聚簇索引可以保证高效快速的主键查询,因为二级索引包含主键列,所以但如果主键占用物理空间过大的话,二级索引占用的空间也会很大,所以如果存在多个索引的情况下,建议适当调小主键索引的大小。

事务的四大特性

  • 原子性Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  • 一致性Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
  • 隔离性Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  • 持久性Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。一致性是一个比较特殊的概念,和AID不同的是,它并非数据库的特性。通过MySQL的AID来保证C,C是目的,AID是手段,由此保证应用层面业务能够从正确的状态转为另一个正确的状态,以保证业务的约束,从而做到一致性。

并发事务带来的问题

丢失更新(Lost Update)

当多个事务同时修改同一数据时,后提交的事务覆盖先提交事务的修改,导致前者的更新失效。

​解决方案​​:

  • 使用行级锁(如 SELECT ... FOR UPDATE)或乐观锁(版本号/时间戳校验);
  • 设置事务隔离级别为可重复读(Repeatable Read)或串行化(Serializable)。

脏读(Dirty Read)

事务读取了其他事务​​未提交​​的数据,若后者回滚,则读取到无效数据。

解决方案​​:

  • 将隔离级别提升至 ​​读已提交(Read Committed)​​ 或更高;
  • 显式加锁(如共享锁)

不可重复读(Non-Repeatable Read)

同一事务内多次读取同一数据,结果因其他事务​​提交修改​​而不同。

解决方案​​:

  • 使用 ​​可重复读(Repeatable Read)​​ 隔离级别(MySQL 默认级别),通过快照保证一致性;
  • 通过行锁锁定数据(如 FOR UPDATE

幻读(Phantom Read)

同一事务内多次查询同一条件,结果集因其他事务​​插入或删除​​数据而变化

解决方案​​:

  • 使用 ​​串行化(Serializable)​​ 隔离级别(牺牲并发性能);
  • 通过 ​​间隙锁(Gap Lock)​​ 或 ​​临键锁(Next-Key Lock)​​ 锁定查询范围(InnoDB 引擎支持)。

不可重复读和幻读有什么区别

  • 不可重复读是针对​​单条数据的修改​​,导致前后读取内容不一致。
  • 幻读是针对​​结果集数量的增减​​,其他事务​​插入(INSERT)或删除(DELETE)​​ ,因数据范围变动产生“幻觉”。

MySQL 四大事务隔离级别

  • READ-UNCOMMITTED(读取未提交) :最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
  • READ-COMMITTED(读取已提交) :允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
  • REPEATABLE-READ(可重复读) :对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • SERIALIZABLE(可串行化) :最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别​​脏读​​不可重复读​​幻读​​实现机制​
​读未提交​❌可能❌可能❌可能无锁或仅共享锁,直接读内存最新数据。
​读已提交(RC)​✅避免❌可能❌可能MVCC+行锁,每次读生成新Read View。
​可重复读(RR)​✅避免✅避免⚠️部分避免MVCC+间隙锁(Gap Lock),事务内复用Read View。
​串行化​✅避免✅避免✅避免全表锁,事务串行执行。

并发事务的控制

MySQL 中并发事务的控制方式无非就两种:MVCC。锁可以看作是悲观控制的模式,多版本并发控制(MVCC,Multiversion concurrency control)可以看作是乐观控制的模式。

锁机制(Locking)

按锁粒度分类
  • 表级锁(Table Lock):锁定整个表,开销小但并发能力差。适用于读多写少的场景。
  • 行级锁(Row Lock):锁定表中的某一行或某些行,提供更高的并发能力,但管理成本较高。InnoDB存储引擎支持行级锁。
    • 记录锁(Record Lock)​​:锁定单行。
    • ​间隙锁(Gap Lock)​​:锁定索引间隙,防幻读(RR 隔离级别生效)。
    • ​临键锁(Next-Key Lock)​​:记录锁+间隙锁组合(InnoDB 默认行锁算法)。
  • 页级锁(Page Lock)BDB 引擎特有,InnoDB 不常用,锁定磁盘上的一个数据页(通常是8KB),介于表级锁和行级锁之间,在一些其他数据库系统中使用,但在MySQL中不常用。
按锁功能分类
  • 共享锁(Shared Lock, S锁):允许事务读取一行数据,多个事务可以同时持有同一数据项的共享锁。
  • 排他锁(Exclusive Lock, X锁):允许事务更新或删除一行数据,当一个事务获得排他锁后,其他任何事务都不能再获取该行的任何类型的锁。
  • 意向锁(Intent Lock):一种表级锁,用于表明事务稍后对表中的行加共享锁排他锁的意图。有意向共享锁(IS)意向排他锁(IX)两种,主要目的是为了提高表级锁的性能,减少锁冲突检测的开销

更详细参考这个:MySQL 锁的使用

多版本并发控制(MVCC)

详细参考:MVCC理解-CSDN博客

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种并发控制机制,可以让多个事务无锁并发执行,提高数据库性能,同时避免脏读、不可重复读等问题。

  • MVCC 主要用于 InnoDB 存储引擎,默认支持 REPEATABLE READ 隔离级别。
  • 通过 数据行的多个版本,使得读操作不会被写操作阻塞,提升并发性能
MVCC 的实现原理
隐藏列(隐式事务 ID 和回滚指针)

InnoDB 为每个数据行额外存储两个隐藏列

  • DB_TRX_ID(6字节):表示最后一次插入或更新该行的事务 id。此外,delete 操作在内部被视为更新,只不过会在记录头 Record header 中的 deleted_flag 字段将其标记为已删除
  • DB_ROLL_PTR(7字节):回滚指针,指向该行的 undo log 。如果该行未被更新,则为空
Undo Log(回滚日志)
  • 作用:存储旧版本数据,使得历史版本可读(多版本存储)。
  • 实现
    • 每次 UPDATE 或 DELETE,都会把旧值存入 Undo Log,并更新 roll_pointer 指向旧版本数据。
    • 事务回滚时,Undo Log 可用于恢复旧数据
Read View(读视图)
  • 作用:控制事务可见性,决定事务是否可以看到某个版本的数据。
  • 字段说明
    creator_trx_id创建该 Read View 的事务 ID(即当前事务 ID)
    m_ids生成 Read View 时,系统中所有活跃(未提交)事务的 ID 列表
    min_trx_idm_ids 中的最小事务 ID
    max_trx_id系统预分配的下一个事务 ID(即当前最大事务 ID+1)
  • 核心逻辑:
    1. 如果该版本的DB_TRX_ID小于min_trx_id,说明该版本在创建ReadView时已经提交,可见

    2. 如果该版本的DB_TRX_ID大于等于max_trx_id,说明该版本在创建ReadView时还未开始,不可见
    3. 如果该版本的DB_TRX_ID在m_ids中,说明该版本在创建ReadView时还未提交,不可见
    4. 如果该版本的DB_TRX_ID等于creator_trx_id,说明该版本是当前事务修改的,可见

 

MVCC 读写方式
​读操作(快照读)​

如 SELECT 语句读取版本链中符合 Read View 的最近历史版本,无需加锁。

​示例​​:事务A启动后,即使事务B修改了数据并提交,事务A仍读取启动时的快照数据。

​写操作(当前读)​

如 UPDATE/DELETE 会创建新版本同时锁定当前行(行锁),并更新 DB_TRX_ID 和 DB_ROLL_PTR

​删除与更新​
  • DELETE:标记行为删除状态,更新 DB_TRX_ID 为删除事务ID。
  • UPDATE:创建新版本,旧版本指针指向 Undo Log。

MySQL索引

B树

B树由于存在多叉,可以大大降低树的高度,减少一次请求中访问磁盘的次数。B树的每个节点包含键值、数据及其指向子节点的指针。如下图所示

B+树

B+Tree是B Tree的一种变体,B+Tree 只在叶子节点存储数据,而 B 树 的非叶子节点也要存储数据。它的所有叶子节点包含了全部数据记录的指针(或直接存储数据),并且叶子节点间通过双向指针相连,形成了一个双向链表,特别适合范围查询和全表扫描。如下图所示:

B树和B+树的主要区别:

  • 数据存储位置:
    • B树:所有节点都存储数据,包括叶子节点和非叶子节点
    • B+树:只有叶子节点存储数据,非叶子节点只存储索引值
  • 叶子节点连接:
    • B树:叶子节点之间没有连接
    • B+树:叶子节点通过指针相连,形成一个有序链表范围查找更快
  • 查询效率:
    • B树:由于数据分布在所有节点,查询时可能在非叶子节点就找到数据
    • B+树:必须查询到叶子节点才能获取数据

MySQL选择B+树作为索引结构的原因

  1. 更快的范围查询和全表扫描: B+树的​​双向链表结构​​将叶子节点按Key顺序串联起来。

  2.  更稳定的查询时间复杂度:​​ 在B+树中,任何查询(无论是等值查询还是范围查询)​​必须到达叶子节点​​才能获得最终数据,所有查询操作都呈现出 O(log n) 的稳定性能。

  3. 更高的空间利用率和更矮的树高:B+树的​​内部节点不存储实际数据​​(仅存储键),因此一个内部节点(例如一个磁盘页,如16KB)可以存储​​更多键​​。

    1. 这意味着B+树在​​相同规模的数据集下,有更小的扇出(Fan Out)​​,树的高度更低。
    2. ​更矮的树 = 更少的磁盘I/O次数。​​ 由于数据库的主要性能瓶颈在于磁盘I/O,减少磁盘访问次数至关重要。定位一个键通常只需要访问2-4层节点,即使对于十亿级别的表。

常见索引

  • 聚簇索引(聚集索引):索引结构和数据一起存放的索引,InnoDB 中的主键索引就属于聚簇索引。
  • 非聚簇索引(非聚集索引):索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。
  • 覆盖索引:覆盖索引即需要查询的字段正好是索引的字段,那么直接根据该索引,就可以查到数据了,而无需回表查询。
  • 联合索引:使用表中的多个字段创建索引,就是 联合索引,也叫 组合索引 或 复合索引

创建索引原则

1. 根据查询频率创建索引:对经常用于查询条件的列创建索引,如WHERE、GROUP BY、ORDER BY、JOIN中的列

2.使用复合索引代替多个单列索引:对于多条件查询,优先考虑创建复合索引,以减少查询时的回表操作。

3.优化数据选择性:优先选择区分度高的列建立索引,对高重复值的列(如布尔值)不建议创建索引。
4.避免过多索引:单表索引数量建议控制在5个以内,每个索引会占用额外的存储空间并影响INSERT、UPDATE、DELETE操作的性能。

5.使用覆盖索引
6 避免冗余索引


索引失效场景

  • 创建了组合索引,但查询条件未遵守最左匹配原则;
  • 在索引列上进行计算、函数、类型转换等操作;
  • 以 % 开头的 LIKE 查询比如 LIKE '%abc';
  • 查询条件中使用 OR,且 OR 的前后条件中有一个列没有索引,涉及的索引都不会被使用到;
  • IN 的取值范围较大时会导致索引失效,走全表扫描(NOT IN 和 IN 的失效场景相同);
  • 发生隐士转换,数据类型类型不匹配时
  • 范围查询后的列索引失效

如何分析Explain结果

​字段名​​说明​​重要注意点​
​id​查询中子句的执行顺序标识符相同 id 按顺序执行;不同 id 时,值越大优先级越高(如子查询)。
​select_type​查询类型:
SIMPLE:简单查询(无子查询或UNION)
PRIMARY:最外层查询
SUBQUERY:子查询
DERIVED:派生表(FROM中的子查询)
UNION:UNION中的第二个或后续查询
DEPENDENT SUBQUERY 表示子查询依赖外部查询,可能影响性能。
​table​当前行访问的表名若使用别名,则显示别名。
​partitions​查询匹配的分区未分区表显示 NULL
​type​​访问表的方式(性能关键指标)​​,性能从高到低排序:
system > const > eq_ref > ref > range > index > ALL
ALL(全表扫描)需优化;range(索引范围扫描)常见于范围查询;const 表示通过主键/唯一索引查到单行。
​possible_keys​可能使用的索引若为 NULL,表示无合适索引。
​key​实际使用的索引若为 NULL,说明未用索引(需检查)。
​key_len​索引使用的字节数长度越小越好;复合索引中可判断使用了哪些部分。
​ref​与索引比较的列或常量显示 const(常量)、列名或 NULL
​rows​​预估扫描的行数​值越小越好;乘积可估算多表关联的总扫描量。
​filtered​返回结果占扫描行数的百分比100% 表示完全匹配;低百分比可能需优化条件。
​Extra​​额外执行信息(优化重点)​​:
Using index:覆盖索引(无需回表)
Using where:使用 WHERE 过滤
Using temporary:使用临时表
Using filesort:额外排序(需优化)
Using index condition:索引条件下推
Using filesort 和 Using temporary 可能成为性能瓶颈。

优化建议:

  1. 如果 type 是 ALL,说明是全表扫描,需要添加适当的索引
  2. 如果 rows 数值很大,说明需要检查的行数多,可能需要优化索引
  3. 如果 Extra 列出现 Using filesort 或 Using temporary,说明需要优化查询语句
  4. 如果 key_len 过长,考虑是否可以使用前缀索引
  5. 如果 possible_keys 有多个,但 key 为 NULL,说明索引可能失效

实际优化步骤:

  1. 首先查看 type 列,确保不是 ALL
  2. 检查是否使用了正确的索引(key 列)
  3. 观察 rows 列,评估扫描的行数
  4. 查看 Extra 列,了解是否有额外的操作
  5. 根据分析结果,添加或修改索引,或重写查询语句

Using filesort 或 Using temporary 怎么优化

1.Using filesort 优化

Using filesort 表示 MySQL 需要进行额外的排序操作,这通常发生在:

  • ORDER BY 子句
  • GROUP BY 子句
  • DISTINCT 操作

2.Using temporary 优化

Using temporary 表示 MySQL 需要创建临时表,通常发生在:

  • GROUP BY 操作
  • ORDER BY 和 GROUP BY 同时使用
  • DISTINCT 操作
  • UNION 操作

MYSQL常见日志

  • 错误日志(error log):对 MySQL 的启动、运行、关闭过程进行了记录。
  • 二进制日志(binary log,binlog):主要记录的是更改数据库数据的 SQL 语句。
  • 一般查询日志(general query log):已建立连接的客户端发送给 MySQL 服务器的所有 SQL 记录,因为 SQL 的量比较大,默认是不开启的,也不建议开启。
  • 慢查询日志(slow query log):执行时间超过 long_query_time 秒钟的查询,解决 SQL 慢查询问题的时候会用到。
  • 事务日志(redo log 和 undo log):redo log 是重做日志,undo log 是回滚日志。
  • 中继日志(relay log):relay log 是复制过程中产生的日志,很多方面都跟 binary log 差不多。不过,relay log 针对的是主从复制中的从库。
  • DDL 日志(metadata log):DDL 语句执行的元数据操作。

二进制日志(binlog)和事务日志(redo log 和 undo log)比较重要。

slow query log(慢查询日志)

慢查询日志记录了执行时间超过 long_query_time(默认是 10s,通常设置为1s)的所有查询语句,在解决 SQL 慢查询(SQL 执行时间过长)问题的时候经常会用到。

找到慢 SQL 是优化 SQL 语句性能的第一步,然后再用EXPLAIN 命令可以对慢 SQL 进行分析,获取执行计划的相关信息。

你可以通过 show variables like "slow_query_log";命令来查看慢查询日志是否开启,默认是关闭的。

mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | OFF   |
+----------------+-------+

通过 SET GLOBAL slow_query_log=ON 命令将其开启

long_query_time 参数定义了一个查询消耗多长时间才可以被定义为慢查询,默认是 10s,通过 SHOW VARIABLES LIKE '%long_query_time%'命令即可查看:


mysql> show variables like '%long_query_time%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

对 long_query_time 参数进行修改:

SET GLOBAL long_query_time=1

binlog(二进制日志)

binlog(binary log 即二进制日志文件) 主要记录了对 MySQL 数据库执行了更改的所有操作(数据库执行的所有 DDL 和 DML 语句),包括表结构变更(CREATE、ALTER、DROP TABLE…)、表数据修改(INSERT、UPDATE、DELETE...),但不包括 SELECT、SHOW 这类不会对数据库造成更改的操作。
 

binlog 通过追加的方式进行写入,大小没有限制。并且,我们可以通过max_binlog_size参数设置每个 binlog 文件的最大容量,当文件大小达到给定值之后,会生成新的 binlog 文件来保存日志,不会出现前面写的日志被覆盖的情况。

binlog 的格式

一共有 3 种类型二进制记录方式:

  • Statement 模式 :每一条会修改数据的sql都会被记录在binlog中,如inserts, updates, deletes。
  • Row 模式 (推荐): 5.7+默认,每一行的具体变更事件都会被记录在binlog中。
  • Mixed 模式 :Statement 模式和 Row 模式的混合。默认使用 Statement 模式,少数特殊具体场景自动切换到 Row 模式。
binlog 核心作用
  1. ​数据恢复​​:通过重放Binlog,可将数据库恢复到任意时间点或特定事务状态,尤其适用于误删数据后的恢复。
  2. ​主从复制​​:主库(Master)将Binlog同步给从库(Slave),从库重放日志实现数据一致性,支撑高可用架构。
  3. ​异构数据同步​​:将Binlog解析后同步到Hive、HBase、Elasticsearch等系统,实现OLTP到OLAP的数据流转。
  4. ​审计与监控​​:记录所有数据变更历史,用于安全审计或实时监控。

binlog 最主要的应用场景是 主从复制 ,主备、主主、主从都离不开binlog,需要依靠 binlog 来同步数据,保证数据一致性。

主从复制流程:

  1.  主库将数据库中数据的变化写入到 binlog
  2. 从库连接主库
  3. 从库会创建一个 I/O 线程向主库请求更新的 binlog
  4. 主库会创建一个 binlog dump 线程来发送 binlog ,从库中的 I/O 线程负责接收
  5. 从库的 I/O 线程将接收的 binlog 写入到 relay log 中。
  6. 从库的 SQL 线程读取 relay log 同步数据本地(也就是再执行一遍 SQL )。

 Canal 数据同步的原理如下图所示:

  1. Canal 模拟 MySQL Slave 节点与 MySQL Master 节点的交互协议,把自己伪装成一个 MySQL Slave 节点,向 MySQL Master 节点请求 binlog;
  2. MySQL Master 节点接收到请求之后,根据偏移量将新的 binlog 发送给 MySQL Slave 节点;
  3. Canal 接收到 binlog 之后,就可以对这部分日志进行解析,获取主库的结构及数据变更。

 redo log(重做日志)

redo log(重做日志)是 InnoDB 存储引擎独有的,它让 MySQL 拥有了崩溃恢复能力。

比如 MySQL 实例挂了或宕机了,重启时,InnoDB 存储引擎会使用 redo log 恢复数据,保证数据的持久性与完整性。


MySQL 中数据是以页为单位,你查询一条记录,会从硬盘把一页的数据加载出来,加载出来的数据叫数据页,会放入到 Buffer Pool 中。后续的查询都是先从 Buffer Pool 中找,没有命中再去硬盘加载,减少硬盘 IO 开销,提升性能。

更新表数据的时候,也是如此,发现 Buffer Pool 里存在要更新的数据就直接在 Buffer Pool 里更新。然后会把“在某个数据页上做了什么修改”记录到重做日志缓存(redo log buffer)里,接着刷盘到 redo log 文件里。

刷盘时机

 InnoDB 将 redo log 刷到磁盘上有几种情况:

  1. 事务提交:当事务提交时,log buffer 里的 redo log 会被刷新到磁盘(可以通过innodb_flush_log_at_trx_commit参数控制)。
  2. log buffer 空间不足时:log buffer 中缓存的 redo log 已经占满了 log buffer 总容量的大约一半左右,就需要把这些日志刷新到磁盘上。
  3. 事务日志缓冲区满:InnoDB 使用一个事务日志缓冲区(transaction log buffer)来暂时存储事务的重做日志条目。当缓冲区满时,会触发日志的刷新,将日志写入磁盘。
  4. Checkpoint(检查点):InnoDB 定期会执行检查点操作,将内存中的脏数据(已修改但尚未写入磁盘的数据)刷新到磁盘,并且会将相应的重做日志一同刷新,以确保数据的一致性。
  5. 后台刷新线程:InnoDB 启动了一个后台线程,负责周期性(每隔 1 秒)地将脏页(已修改但尚未写入磁盘的数据页)刷新到磁盘,并将相关的重做日志一同刷新。
  6. 正常关闭服务器:MySQL 关闭的时候,redo log 都会刷入到磁盘里去。

我们要注意设置正确的刷盘策略innodb_flush_log_at_trx_commit 。根据 MySQL 配置的刷盘策略的不同,MySQL 宕机之后可能会存在轻微的数据丢失问题

innodb_flush_log_at_trx_commit 的值有 3 种,也就是共有 3 种刷盘策略:

  • 0:设置为 0 的时候,表示每次事务提交时不进行刷盘操作。这种方式性能最高,但是也最不安全,因为如果 MySQL 挂了或宕机了,可能会丢失最近 1 秒内的事务。
  • 1:设置为 1 的时候,表示每次事务提交时都将进行刷盘操作。这种方式性能最低,但是也最安全,因为只要事务提交成功,redo log 记录就一定在磁盘里,不会有任何数据丢失。
  • 2:设置为 2 的时候,表示每次事务提交时都只把 log buffer 里的 redo log 内容写入 page cache(文件系统缓存)。page cache 是专门用来缓存文件的,这里被缓存的文件就是 redo log 文件。这种方式的性能和安全性都介于前两者中间。

刷盘策略innodb_flush_log_at_trx_commit 的默认值为 1,设置为 1 的时候才不会丢失任何数据。为了保证事务的持久性,我们必须将其设置为 1。

InnoDB 存储引擎有一个后台线程每隔1 秒,就会把 redo log buffer 中的内容写到文件系统缓存(page cache),然后调用 fsync 刷盘。所以宕机可能会丢失1s数据。

文件组

硬盘上存储的 redo log 日志文件不只一个,而是以一个日志文件组的形式出现的,每个的redo日志文件大小都是一样的。

比如可以配置为一组4个文件,每个文件的大小是 1GB,整个 redo log 日志文件组可以记录4G的内容。

它采用的是环形数组形式,从头开始写,写到末尾又回到头循环写,如下图所示。

  • ​指针管理​​:
    • write pos:当前写入位置。
    • checkpoint:已刷盘数据的擦除位置。

write pos 表示 redo log 当前记录写到的位置, check point 表示当前要擦除的位置。当write pos追上check point时,表示 redo log 文件被写满了。这个时候,MySQL 没办法执行更新操作,也就是说数据库更新操作会被阻塞,因为无法再写入 redo log 日志。为了保证 MySQL 更新操作的正常执行,需要执行 CheckPoint 刷盘机制。CheckPoint 会按照一定的条件将内存中的脏页刷到磁盘上。成功刷盘之后,checkpoint 会向后移动(顺时针方向)。这样的话,才能继续写入 redo log 日志,阻塞的更新操作才能继续执行。

什么情况下会出现数据丢失?redo log 如何保证事务的一致性?

  1. redo log 写入 log buffer 但还未写入 page cache ,此时数据库崩溃,就会出现数据丢失(刷盘策略innodb_flush_log_at_trx_commit 的值为 0 时可能会出现这种数据丢失);
  2. redo log 已经写入 page cache 但还未写入磁盘,操作系统奔溃,也可能出现数据丢失(刷盘策略innodb_flush_log_at_trx_commit 的值为 2 时可能会出现这种数据丢失)。
  3. innodb_flush_log_at_trx_commit为3,redo log一定写入硬盘,保证了事务的一致性。

undo log(撤销日志)

Undo Log(撤销日志)是数据库事务管理中的核心组件,主要用于记录数据修改前的状态,确保事务的​​原子性​​(Atomicity)和​​多版本并发控制​​(MVCC)。

核心作用​
  1. 事务回滚(保证原子性)​

    • 当事务执行失败或主动回滚(ROLLBACK)时,Undo Log 提供逆向操作恢复数据至原始状态。
    • ​逻辑日志设计​​:
      • ​INSERT​​ → 记录删除操作(通过主键定位删除);
      • ​DELETE​​ → 记录插入操作(保存被删数据的完整值);
      • ​UPDATE​​ → 记录旧值(用于还原字段)。
  2. ​多版本并发控制(MVCC)​

    • 为不同事务提供数据的历史版本快照,实现​​非阻塞读取​​(快照读)。
    • ​实现原理​​:
      • 每条记录通过隐藏字段 DB_TRX_ID(事务ID)和 DB_ROLL_PTR(回滚指针)形成版本链;
      • 读操作根据事务的 ​​ReadView​​(可见性规则)选择合适的历史版本

相关文章:

  • 脑洞大开,将文本存入视频中
  • 【.net core】.KMZ文件解压为.KML文件并解析为GEOJSON坐标数据集。附KML处理多线(LineString)闭环问题
  • PPIO ×Apifox:一键调用模型API,高效开发AI应用
  • AdvancedLivePortrait V2版 - 一张照片生成生动任意表情图片/视频,支持50系显卡 本地一键整合包下载
  • 【教学类】20250605立体纸盘(3边形-22边形,角度5、10……40,45)
  • 知识蒸馏:从模型输出到深层理解
  • 【QQMusic】在LikePage点击取消喜欢没有反应
  • OptiStruct结构分析与工程应用:无限元分析指南
  • graylog收集rsyslog实现搜索解析
  • JS手写代码篇---bind手写
  • python摆放花盆 2023年信息素养大赛复赛/决赛真题 小学组/初中组 python编程挑战赛 真题详细解析
  • 如何利用Haption力反馈遥操作机器人解决远程操作难题
  • 25_06_05Ubuntu系统root密码破解
  • ros2--大数据包丢帧问题
  • 【DAY40】训练和测试的规范写法
  • 全国邮政编码,包括:省份 市 县区 长途区号 邮政编码
  • EFI(x64)简易开发环境
  • JavaScript 循环方法对比指南
  • 什么是软中断、硬中断
  • World of Warcraft [Vault of Archavon][Reins of the Grand Black War Mammoth]
  • 辽源市建设局网站/怎么样创建网站
  • wordpress文件上传限制/西安seo排名
  • 云南网站开发公司介绍/seo教程书籍
  • 外贸手机商城网站建设 深圳/茶叶网络推广方案
  • 做微商能利用的网站有哪些问题/智谋网站优化公司
  • thinkphp 网站开发/百度广告搜索推广