Mysql 知识整理

数据库三大范式

第一范式:每个列都不可以再拆分。

Mysql 知识整理

第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。

Mysql 知识整理

第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。

Mysql 知识整理

SQL语言共分为四大类

  1. 数据查询语言(DQL):用于从数据库中查询数据。常用的 DQL 命令是 select,它允许用户指定要从数据库中检索哪些数据。通过 select 语句,你可以选择特定的列、过滤数据、排序结果等。
  2. 数据定义语言(DDL):用于定义和管理数据库中的结构。DDL 命令用于创建、修改和删除数据库、表、索引、视图等对象。常见的 DDL 命令包括 create、alter 和 drop。
  3. 数据操纵语言(DML):用于操作数据库中的数据。DML 命令允许你插入、更新和删除数据。常用的 DML 命令包括 insert、update 和 delete。
  4. 数据控制语言(DCL):用于控制数据库用户的权限和访问级别。DCL 命令允许管理员授权或撤销用户对数据库对象的访问权限。常见的 DCL 命令包括 grant 和 revoke。
类别英文缩写中文含义作用关键词常见语句
DDLData Definition数据定义定义结构CREATEALTERDROP
DMLData Manipulation数据操作增删改数据INSERTUPDATEDELETE
DQLData Query数据查询查找数据SELECT
DCLData Control权限控制分配/撤销权限GRANTREVOKE

索引

MySQL 索引
 ├── 功能角度(逻辑类型)
 │   ├── 主键索引(Primary Key)
 │   ├── 唯一索引(Unique Index)
 │   ├── 普通索引(Normal Index)
 │   ├── 联合索引(Composite Index)
 │   ├── 全文索引(Fulltext Index)
 │   └── 空间索引(Spatial Index)
 │
 └── 存储结构角度(物理结构)
     ├── 聚簇索引(Clustered Index)= 主键索引
     ├── 二级索引(Secondary Index)= 辅助索引

创建索引的原则

原则总结是否推荐建索引?
查询条件字段
区分度高的字段
联合索引按顺序使用
尽量实现覆盖查询
控制索引数量(别太多)⚠️ 慎重
频繁更新字段❌ 尽量避免
长文本字段避免建索引❌ 避免
函数、运算字段索引失效❌ 避免
重复率高字段不推荐索引❌ 避免
外键字段明确加索引

MySQL为什么使用B+树作为索引的数据结构

B+Tree vs B Tree:

  • 存储相同数据量级别的情况下,B+Tree树高比 B Tree低,磁盘IO次数更少。
  • B+Tree叶子节点用双向链表串起来,适合范围查询,BTree无法做到这点

B+Tree vs二叉树:

  • 随着数据量的增加,二叉树的树高会越来越高,磁盘IO次数也会更多,B+Tree在千万级别的数据量下,高度依然维持在3~4层左右,也就是说一次数据查询操作只需要做3~4次的磁盘O操作就能查询到目标数据。

B+Tree vs Hash:

  • 虽然Hash的等值查询效率很高,但是无法做范围查询

索引失效有哪些?

场景/错误写法原因是否失效
WHERE UPPER(name) = 'XX'函数操作
WHERE age != 30使用不等于
WHERE name LIKE '%三'通配符在前
WHERE name = '张三' OR age = 20OR 条件中部分无索引
WHERE age = 20 联合索引跳过最左字段最左前缀原则不符合
WHERE phone = 1234567890(字段是字符串)类型不一致,触发隐式转换
小表查索引优化器判断索引没必要✅(可能)

什么时候需要 / 不需要创建索引?

是否建索引?场景 / 条件
✅ 需要频繁 WHERE 查询、JOIN排序分组唯一字段
✅ 需要大表中的范围查询字段、外键字段、联合索引中最左字段
❌ 不需要数据重复度高、字段频繁更新、字段很少被查询
❌ 不需要极小的表、临时表、字段本身参与计算或函数
  • 读多写少 → 建索引优先(查询系统)
  • 写多读少 → 谨慎建索引(日志、消息系统)
  • 建索引之后要配合 EXPLAIN 分析是否命中

有什么优化索引的方法?

  • 前缀索引优化;
  • 覆盖索引优化;
  • 主键索引最好是自增的;
  • 防止索引失效
项目前缀索引联合索引覆盖索引
是不是一种索引类型✅ 是✅ 是❌ 否,是一种查询优化结果
是否在建索引时定义✅ 是✅ 是❌ 否,由查询命中索引字段决定
适用字段仅限字符串类型(CHAR/VARCHAR等)任意字段类型查询中字段全部包含在索引中即可
关键作用节省空间,适合长字段多字段组合索引,支持多条件查询避免回表,提升查询效率
是否可以唯一✅ 可以(但容易冲突)✅ 可以(可建联合唯一索引)❌ 不属于索引类型
是否回表✅ 可能(字段不完整)✅ 可能(视查询字段而定)❌ 不需要

EXPLAIN 常见字段汇总(重点关注这几个)

Mysql 知识整理

type(连接类型)🌟最重要的性能指标之一

type含义效率
system表仅有一行(系统表)极高
const一次命中,结果恒定 极高
eq_ref主键/唯一索引的等值查询 非常好
ref非唯一索引的等值查询
range范围查询,如 BETWEENLIKE 'xx%' 不错
index全索引扫描(不回表)⚠️ 中等
ALL全表扫描

key(使用的索引名称)

显示 MySQL 实际使用的索引名称。

  • 如果是 NULL → 没有使用索引 ❌
  • 如果是索引名 → 说明命中索引 ✅

rows(扫描的行数)

表示 MySQL 预估要读取的行数(越少越好):

  • 小于 100:查询很快
  • 上万以上:说明可能需要优化

✅ 注意:这里是估算值,并非真实执行统计。

Extra(额外信息,能看出是否回表)

Extra 内容含义说明
Using index✅ 覆盖索引,无需回表,性能最佳
Using index condition✅ 使用了索引条件下推(ICP)
Using where有使用 WHERE 条件(不是坏事)
Using temporary❌ 用了临时表(常见于复杂排序或分组)
Using filesort❌ 用了文件排序,可能意味着索引未用于 ORDER BY

事务

事务(ACID)有哪些特性?

特性说明(通俗理解)
A 原子性要么都做,要么一个都不做(不可拆分)
C 一致性数据操作前后都保持规则/约束一致
I 隔离性多个事务之间互不干扰
D 持久性提交成功后数据永不丢失

事务必须要遵守 4 个特性,分别如下:

  • 原子性(Atomicity:一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态。
  • 一致性(Consistency:是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 不论如何转账,最后的结果是1400 元。
  • 隔离性(Isolation:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。
  • 持久性(Durability:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?

  • 持久性是通过 redo log (重做日志)来保证的;
  • 原子性是通过 undo log(回滚日志) 来保证的;
  • 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
  • 一致性则是通过持久性+原子性+隔离性来保证;

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

异常类型描述
脏读读到了别的事务未提交的数据
不可重复读同一事务两次读到的结果不同(被别人修改了)
幻读同一事务两次查询,新增或删除了行数
  • 脏读(Drity Read):一个事务读取另一个事务未提交的数据
  • 不可重复读(Non-repeatable read):一个事务对同一数据进行读取,前后数据内容不一致
  • 幻读(Phantom Read):一个事务内进行了多次读取,数据总量不一致。
Mysql 知识整理

事务的隔离级别有哪些?

隔离级别脏读不可重复读幻读
未提交读(READ-UNCOMMITTED)
已提交读(READ-COMMITTED)×
可重复读(REPEATABLE-READ)××
可串行(SERIALIZABLE)×××
  • 读未提交(read uncommitted,指一个事务还没提交时,它做的变更就能被其他事务看到;
  • 读提交(read committed,指一个事务提交之后,它做的变更才能被其他事务看到;
  • 可重复读(repeatable read,指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别
  • 串行化(serializable;会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;

按隔离水平高低排序如下:

Mysql 知识整理

MVCC

它的实现原理主要是版本链,undo日志 ,Read View来实现的。即多版本并发控制,主要是为了提高数据库的并发性能。

版本链

除了我们数据库每行的数据,还有几个隐藏字段,分别是事务ID(trx_id),一个是回滚指针(roll_pointer)。

trx_id :每次一个事务对某条聚簇索引记录改动时,都会把自己的事务id重新写到 trx_id 隐藏列。

roll_pointer :每次对某条聚簇索引记录进行改动时,都会把旧版本记录写入到 undo日志中,roll_pointer这个隐藏列是一个地址指针,通过它可以找到该聚簇索引记录历史修改信息。

undo日志

Undo log 主要用于记录数据被修改之前的日志,在表信息修改之前先会把数据拷贝到undo log里。当事务进行回滚时可以通过undo log 里的日志进行数据还原。

undo log主要分为两种:

insert undo log:顾名思义,此代表执行insert语句时产生的undo log, 它只在事务回滚时需要,因为这种log只是对本事务可见,其他事务不可见,所以当事务提交后,这种类型的undo log就会被系统直接删除回收(也就是该undo log占用的undo页面链表被释放)。

update undo log(主要):事务在进行update或者delete时产生的undo log; 不仅在事务回滚时需要,在快照读时也需要(也就是MVCC),所以不能在事务提交后马上删除,只在提交后放入undo log的链表,等待purge线程进行最后的删除。

Read View读视图

什么是Read View?

Read View 是当前事务在执行“快照读”时生成的一份“可见数据版本清单”,用于判断当前能“看见哪些事务提交的数据”。

通俗地说:

Read View 就像是当前事务“拍下的一张快照”,它决定了你在事务中看到的“历史数据版本”。

元素说明
m_ids当前系统中活跃事务的 ID 列表(未提交)
min_trx_id活跃事务中最小的事务 ID,用于加速判断
max_trx_id当前系统中尚未分配的下一个事务 ID(即分配到的最大事务 ID + 1)
creator_trx_id当前事务自己的 ID,用于标识“自己是否能看到自己”

creator_trx_id :指创建该 Read View 的事务的事务 id。

m_ids :指创建该 Read View 时数据库中所有活跃事务的事务 id 列表,这是一个列表,活跃事务则代表是已启动但未提交的事务。

min_trx_id :指创建 Read View 时数据库中活跃事务中最小的事务 id,也就是 m_ids 中的最小值。

max_trx_id :这里并不是m_ids中的最大值,而是创建 Read View 时当前数据中应该给下一个事务的id值,也就是全局事务中最大的事务id值+ 1。

在可重复读隔离级别下,Read View是在事务开始(begin)之后且执行第一条sql时创建,创建Read View的同时也就生成了一个新的事务id(直到commit结束),事务会依赖该 Read View保证查询结果保持不变直到该事务结束。

Read View 的判断规则(事务可见性判断)

条件是否可见原因说明
trx_id < min_trx_id✅ 可见已经提交了,早于其他活跃事务
trx_id = creator_trx_id✅ 可见自己修改的当然能看到
trx_id > max_trx_id❌ 不可见是后面新开的事务,还未开始 → 不可见
trx_id ∈ [min_trx_id, max_trx_id) 且 trx_id ∈ m_ids❌ 不可见活跃事务依然活跃着(还没提交事务)
trx_id ∈ [min_trx_id, max_trx_id) 且 trx_id ∉ m_ids✅ 可见事务虽启动时已存在,但已提交,可见

一个事务去访问记录的时候,除了自己的更新记录总是可见之外,还有这几种情况:

  • 如果记录的 trx_id 值小于 Read View 中的 min_trx_id 值,表示这个版本的记录是在创建 Read View 已经提交的事务生成的,所以该版本的记录对当前事务可见
  • 如果记录的 trx_id 值等于当前事务id,就是自己的事务自己处理,所以总是可见
  • 如果记录的 trx_id 值大于 Read View 中的 max_trx_id 值,表示这个版本的记录是在创建 Read View 才启动的事务生成的,所以该版本的记录对当前事务不可见
  • 如果记录的 trx_id 值在 Read View 的 min_trx_id 和 max_trx_id 之间,需要判断 trx_id 是否在m_ids列表中:
  • 如果记录的 trx_id m_ids 列表中,表示生成该版本记录的活跃事务依然活跃着(还没提交事务),所以该版本的记录对当前事务不可见
  • 如果记录的 trx_id 不在 m_ids列表中,表示生成该版本记录的活跃事务已经被提交,所以该版本的记录对当前事务可见

可重复读(RR)隔离级别是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View

读提交(RC)隔离级别是在每次读取数据时,都会生成一个新的 Read View

Read View 何时生成?

读方式是否创建 Read View是否加锁说明
SELECT * FROM table✅ 是❌ 否快照读,用 Read View 构建数据版本
SELECT ... FOR UPDATE❌ 否✅ 是当前读,直接加锁
UPDATE / DELETE❌ 否✅ 是当前读

MySQL有那些锁?

MySQL 锁
├── 全局锁(Global Lock)
│   └── FTWRL(Flush Tables with Read Lock)
│       ├─ 锁住整个实例,所有库所有表 → 只读维护操作
│       └─ 常用于备份/主从复制初始化
│
├── 表级锁(Table Lock)
│   ├── 表锁(Table Lock)              -- `LOCK TABLES`
│   ├── 元数据锁(Meta Lock)           -- 执行 DDL 时自动加(如 `ALTER TABLE`)
│   ├── 意向锁(Intention Lock)        -- 行锁前提 → 意向共享(IS) / 意向排它(IX)
│   └── AUTO-INC 锁(自增锁)           -- 旧版使用表级锁,8.0 后为轻量级互斥锁
│
└── 行级锁(Row Lock) ← InnoDB 专属
    ├── Record Lock(记录锁)
    │   └─ 锁住某一具体数据行,精确控制并发
    ├── Gap Lock(间隙锁)
    │   └─ 锁住“记录之间的空隙”,防止插入 → 用于防止幻读
    └── Next-Key Lock(临键锁)
        └─ Record Lock + Gap Lock,锁住行 + 间隙,最常见(默认加锁方式)

全局锁(Global Lock)

▶ 类型:FTWRL(Flush Tables With Read Lock)

📌 特点:

  • 会锁住整个 MySQL 实例:所有数据库、所有表
  • 所有对数据的读写都将被阻塞(DML + DDL)
  • 常用于逻辑备份(mysqldump),保证备份期间数据一致

✅ 示例:

FLUSH TABLES WITH READ LOCK;
-- 所有库所有表只读,其他事务无法写入

🔓 解锁:

UNLOCK TABLES;

表级锁(Table Lock)

1. 表锁(Table Lock)

📌 特点:

  • 显式锁定整张表,读或写时阻塞其他用户
  • 常用于 MyISAM 引擎(无行锁)

✅ 示例:

//表级别的共享锁,也就是读锁;
//允许当前会话读取被锁定的表,但阻止其他会话对这些表进行写操作。
lock tables t_student read;

//表级别的独占锁,也就是写锁;
//允许当前会话对表进行读写操作,但阻止其他会话对这些表进行任何操作(读或写)。
lock tables t_stuent write;

需要注意的是,表锁除了会限制别的线程的读写外,也会限制本线程接下来的读写操作。比如我在当前线程执行了select * from t_student; 我就不能执行update及其他语句,也不能执行其他表查询.

2. 元数据锁(Meta Data Lock, MDL)

📌 特点:

  • 自动加锁,用于防止 DDL / DML 冲突
  • 执行 SELECT 时也会加共享 MDL 锁,防止别人同时改表结构

✅ 示例:

-- 会话 A
SELECT * FROM user;

-- 会话 B
ALTER TABLE user ADD COLUMN email VARCHAR(100);
-- ❌ 阻塞!直到 A 释放锁

3. 意向锁(Intention Lock)

📌 特点:

  • InnoDB 自动加的表级锁,不需要显式处理
  • 用于表示“即将”对某一行加锁
  • 有两种:
  • IS:意向共享锁(用于 SELECT … LOCK IN SHARE MODE)
  • IX:意向排它锁(用于 SELECT … FOR UPDATE、UPDATE 等)

✅ 示例:

-- 先在表上加上意向共享锁,然后对读取的记录加共享锁
select ... lock in share mode;

-- 你执行 FOR UPDATE 时,InnoDB 自动加 IX 意向锁
SELECT * FROM user WHERE id=1 FOR UPDATE;

执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的。

4. AUTO-INC 锁(自增锁)

📌 特点:

  • 控制自增列的生成
  • MySQL 5.x 是表级锁,多个事务串行插入
  • MySQL 8.0 优化为轻量级互斥锁,并发更高效

✅ 示例:

INSERT INTO order (user_id, product_id) VALUES (1, 100);
-- 自动生成主键 id,需要加 AUTO-INC 锁来顺序保证

行级锁(Row Lock)(InnoDB 专属)

1. Record Lock(记录锁)

📌 特点:

  • 精确锁住某一行
  • 用于排它性访问(FOR UPDATEUPDATE

✅ 示例:

SELECT * FROM user WHERE id = 1 FOR UPDATE;
-- 精确加锁,仅锁住 id=1 那一行

2. Gap Lock(间隙锁)

📌 特点:

  • 锁住“某两个记录之间的间隙”,阻止插入操作
  • 解决幻读问题(比如防止插入张三)

✅ 示例:

SELECT * FROM user WHERE age > 30 FOR UPDATE;
-- age=40 存在,那么 (30, 40) 的间隙被锁住,不能插入 age=35 的行

3. Next-Key Lock(临键锁)

📌 特点:

  • InnoDB 默认使用的锁类型
  • 等于 Record Lock + Gap Lock
  • 能锁住已有行及其前间隙,全面防止幻读

✅ 示例:

UPDATE user SET age=age+1 WHERE age BETWEEN 30 AND 40;
-- 会锁住 30 到 40 范围内的所有记录 + 相关间隙(Next-Key Lock)

总结表格(核心对照)

类别锁类型场景阻塞其他事务是否防幻读
全局锁FTWRL备份、主从✅ 是✅ 是
表级锁表锁LOCK TABLES✅ 是❌ 否
表级锁元数据锁ALTER TABLE, SELECT✅ 是❌ 否
表级锁意向锁自动加,用于协同行锁❌ 否❌ 否
表级锁AUTO-INC 锁插入自增主键时部分情况会❌ 否
行级锁Record Lock精确主键查询 + FOR UPDATE✅ 是❌ 否
行级锁Gap Lock范围查询✅ 是✅ 是
行级锁Next-Key Lock范围更新/查询 + 防幻读✅ 是✅ 是

按锁的粒度划分:

锁粒度说明引擎
表级锁锁定整张表,开销小、并发差MyISAM、InnoDB(如 LOCK TABLES
行级锁锁定一行记录,开销大、并发高✅ InnoDB
页级锁锁定一页(多个记录),介于表和行之间BDB(较少使用)

按锁的类型划分:

锁类型说明示例语句
共享锁(S锁)允许多个事务并发读取,但不能写入SELECT ... LOCK IN SHARE MODE
排它锁(X锁)只允许一个事务读写,其他事务被阻塞SELECT ... FOR UPDATEUPDATE
意向锁事务声明自己将对某行加锁的意图自动加,用户不可见

按加锁方式划分:

加锁方式说明示例
显式加锁手动加锁LOCK TABLE, FOR UPDATE
隐式加锁InnoDB 自动加锁执行 UPDATE / DELETE 时自动

各类锁的使用/触发举例

SQL 操作加锁方式涉及锁类型
LOCK TABLE users READ显式表锁表级锁
SELECT * FROM users快照读(无锁)使用 MVCC
SELECT * FROM users FOR UPDATE当前读(加锁)行锁 / Gap Lock / Next-Key Lock
UPDATE users SET name='a' WHERE id=1当前读(加锁)行锁 / Next-Key Lock
ALTER TABLE系统自动加锁元数据锁
INSERT INTO auto_table VALUES (...)自动自增锁(AUTO-INC 锁)

特别注意的“锁误区”:

易混点正确解释
“SELECT 会不会加锁?”普通 SELECT 是快照读 → 不加锁(MVCC)
“意向锁是你手动加的吗?”❌ 不是,InnoDB 自动加,用于辅助判断是否能加行锁
“Gap Lock 也会锁住已有记录吗?”❌ 不会,Gap Lock 只锁间隙,不锁记录本身
“Next-Key Lock 是什么意思?”记录锁 + 间隙锁一起加,防止幻读的默认策略
“AUTO-INC 锁会阻塞插入吗?”✅ 会,在老版本中(表级锁),8.0 起是轻量级

隔离级别与锁的关系

在未提交度级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突

在已提交度级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁;

在可重复度级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。

可串行化是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。

什么是死锁?怎么解决?

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

常见的解决死锁的方法

  1. 如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。
  2. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
  3. 对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;

如果业务处理不好可以用分布式事务锁或者使用乐观锁

日志

Mysql 知识整理

undo log、redo log、binlog 有什么用?

undo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC。

redo log(重做日志):是 Innodb 存储引擎层生成的日志,实现了事务中的持久性,主要用于掉电等故障恢复;

binlog (归档日志):是 Server 层生成的日志,主要用于数据备份和主从复制;

为什么需要 undo log?

  • 实现事务回滚,保障事务的原子性。事务处理过程中,如果出现了错误或者用户执 行了 ROLLBACK 语句,MySQL 可以利用 undo log 中的历史数据将数据恢复到事务开始之前的状态。
  • 实现 MVCC(多版本并发控制)关键因素之一。MVCC 是通过 ReadView + undo log 实现的。undo log 为每条记录保存多份历史数据,MySQL 在执行快照读(普通 select 语句)的时候,会根据事务的 Read View 里的信息,顺着 undo log 的版本链找到满足其可见性的记录。

主从复制是怎么实现?

MySQL 的主从复制依赖于 binlog ,也就是记录 MySQL 上的所有变化并以二进制形式保存在磁盘上。复制的过程就是将 binlog 中的数据从主库传输到从库上。

这个过程一般是异步的,也就是主库上执行事务操作的线程不会等待复制 binlog 的线程同步完成。

Mysql 知识整理

MySQL 集群的主从复制过程梳理成 3 个阶段:

  • 写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。
  • 同步 Binlog:把 binlog 复制到所有从库上,每个从库把 binlog 写到暂存日志中。
  • 回放 Binlog:回放 binlog,并更新存储引擎中的数据。

为什么需要 Buffer Pool?

  • 当读取数据时,如果数据存在于 Buffer Pool 中,客户端就会直接读取 Buffer Pool 中的数据,否则再去磁盘中读取。
  • 当修改数据时,如果数据存在于 Buffer Pool 中,那直接修改 Buffer Pool 中数据所在的页,然后将其页设置为脏页(该页的内存数据和磁盘上的数据已经不一致),为了减少磁盘I/O,不会立即将脏页写入磁盘,后续由后台线程选择一个合适的时机将脏页写入到磁盘。

Innodb引擎SQL执行的BufferPool缓存机制

Mysql 知识整理

为什么需要 redo log ?

redo log 是物理日志,记录了某个数据页做了什么修改,每当执行一个事务就会产生这样的一条或者多条物理日志。

在事务提交时,只要先将 redo log 持久化到磁盘即可,可以不需要等到将缓存在 Buffer Pool 里的脏页数据持久化到磁盘。

当系统崩溃时,虽然脏页数据没有持久化,但是 redo log 已经持久化,接着 MySQL 重启后,可以根据 redo log 的内容,将所有数据恢复到最新的状态。

redo log 和 undo log 区别在哪?

这两种日志是属于 InnoDB 存储引擎的日志,它们的区别在于:

  • redo log 记录了此次事务「完成后」的数据状态,记录的是更新之后的值;
  • undo log 记录了此次事务「开始前」的数据状态,记录的是更新之前的值;

redo log 什么时候刷盘?

主要有下面几个时机:

  • MySQL 正常关闭时;
  • 当 redo log buffer 中记录的写入量大于 redo log buffer 内存空间的一半时,会触发落盘;
  • InnoDB 的后台线程每隔 1 秒,将 redo log buffer 持久化到磁盘。

为什么需要 binlog ?

MySQL 在完成一条更新操作后,Server 层还会生成一条 binlog,等之后事务提交的时候,会将该事物执行过程中产生的所有 binlog 统一写 入 binlog 文件。

binlog 文件是记录了所有数据库表结构变更和表数据修改的日志,不会记录查询类的操作,比如 SELECT 和 SHOW 操作。

binlog有几种录入格式?分别有什么区别?

有三种格式,statement,row和mixed。

  • statement模式下,每一条会修改数据的sql都会记录在binlog中。不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。
  • row级别下,不记录sql语句上下文相关信息,仅保存哪条记录被修改。记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大。
  • mixed,一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
Python文章软件

 FinalShell专业版激活

2025-7-11 11:27:45

文章

白嫖 .com .net .jp .shop .xyz 等顶级域名

2025-7-19 22:33:33

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索