目录
前言
MySQL索引
一、概述
二、索引分类
(一)按功能特性分类
(二)按存储方式分类
(三)按数据结构分类
(四)按索引字段数量分类
三、索引的优缺点
(一)优点
(二)缺点
四、普通索引的使用
(一)使用规则
(二)创建索引
建表时创建
建表后添加
(三) 查看索引
(四)删除索引
(五)验证查询是否使用索引
(六)索引使用建议
五、其它索引的使用
(一)唯一索引
(二)复合索引
(三)主键索引
慢SQL分析与优化
一、定义
二、常见原因
三、影响
四、如何发现慢SQL
(一)开启慢查询日志
(二)重启MySQL服务
(三)查看慢日志文件路径
(四)分析慢查询日志
五、如何优化慢SQL
(一)优化查询语句
(二)优化数据库结构
(三)调整数据库配置
(四) 硬件和系统优化
(五)使用性能分析工具
六、优化示例
(一)对索引字段使用函数导致索引失效
优化前
问题分析
优化后
优化说明
验证方法
(二)模糊查询导致索引失效
优化前
问题分析
优化后
优化说明
验证方法
(三)隐式类型转换导致索引失效
优化前
问题分析
优化后
优化说明
验证方法
(四)联合索引未遵循最左前缀原则
优化前
问题分析
优化后
优化说明
验证方法
优化案例
一、案例背景
二、优化过程
(一)问题定位
开启慢查询日志
使用 EXPLAIN 分析执行计划
(二)优化方案
索引优化
SQL 改写
归档历史数据
(三)最终优化组合
三、优化总结
锁机制与并发优化
一、事务与锁机制
(一)SQL 语句类型
(二)事务
(三)ACID 特性
二、锁机制
(一)全局锁
介绍
作用
示例
解释
(二)表级锁
介绍
作用
示例
解释
(三)行级锁
介绍
作用
示例
解释
(四)元数据锁
介绍
作用
示例
解释
三、锁机制在MySQL优化中的价值
前言
- 前面几篇博客已经详细介绍了MySQL的基本使用(查询、建表、备份、主从同步、读写分离、分库分表),感兴趣的可以点击主页查看。
MySQL索引
一、概述
- 索引是数据库中用于提高查询效率的数据结构,类似于书籍的目录。
- 通过索引,数据库可以快速定位到目标数据,避免全表扫描,从而显著提升查询性能。
二、索引分类
(一)按功能特性分类
索引类型 | 功能描述 |
---|---|
普通索引 | 最基本的索引类型,仅用于加速查询,无唯一性约束。 |
唯一索引 | 保证索引列的值唯一,允许存在 NULL 值。 |
主键索引 | 特殊的唯一索引,不允许 NULL 值,每个表只能有一个主键索引。 |
注:本文主要介绍普通索引的使用。
(二)按存储方式分类
索引类型 | 功能描述 |
---|---|
聚簇索引 | 数据行与索引存储在一起,索引顺序即数据物理存储顺序。 InnoDB 中主键默认为聚簇索引。 |
非聚簇索引 | 索引与数据分开存储,索引中仅保存指向数据行的指针。 |
注:InnoDB 存储引擎中,聚簇索引即为主键索引,非聚簇索引也称为二级索引。
(三)按数据结构分类
索引类型 | 功能描述 |
---|---|
B-Tree 索引 | MySQL 默认索引类型,支持范围查询和排序操作,适用于大多数场景。 |
哈希索引 | 基于哈希表实现,仅支持等值查询,不支持范围查询,Memory 引擎支持。 |
全文索引 | 用于对大文本字段进行关键词搜索,支持自然语言查询,InnoDB 和 MyISAM 支持。 |
空间索引 | 用于地理空间数据类型(如 POINT、POLYGON),支持空间查询,MyISAM 支持。 |
(四)按索引字段数量分类
索引类型 | 功能描述 |
---|---|
单列索引 | 仅作用于单个字段,适用于简单查询条件。 |
复合索引(组合索引) | 作用于多个字段,遵循“最左前缀”原则,适用于多条件查询。 |
最左前缀原则:复合索引中,查询条件必须从索引的最左侧字段开始匹配,才能有效使用索引。
三、索引的优缺点
(一)优点
列举 | 描述 |
---|---|
提高查询速度 | 通过索引结构快速定位数据,显著减少查询时间。 |
减少数据扫描量 | 避免全表扫描,降低服务器负载。 |
避免排序和临时表 | 索引本身有序,支持 ORDER BY 和 GROUP BY ,减少额外排序开销。 |
优化磁盘 I/O | 将随机 I/O 转换为顺序 I/O,提高磁盘访问效率。 |
(二)缺点
列举 | 描述 |
---|---|
降低更新效率 | 插入、更新、删除操作需同步维护索引,增加写入开销。 |
占用额外空间 | 索引文件占用磁盘空间,复合索引或大表索引空间开销显著。 |
对低选择性字段效果差 | 字段重复值多时,索引过滤效果不明显,甚至可能不如全表扫描。 |
小表查询收益低 | 数据量较小时,全表扫描成本更低,索引优势不明显。 |
四、普通索引的使用
(一)使用规则
规则 | 说明 |
---|---|
索引数量 | 一个表中可以创建多个普通索引。 |
字段类型 | 支持为任意数据类型的字段创建索引。 |
值约束 | 字段值允许重复,也允许为 NULL。 |
使用场景 | 通常在为 WHERE 子句提供条件的字段上创建索引,以提高查询效率。 |
索引标志 | 普通索引在表结构中标志为 MUL (Multiple Key)。 |
(二)创建索引
建表时创建
CREATE TABLE 库.表(
字段列表,
INDEX(字段名),
INDEX(字段名)
);
# 创建表时添加索引
CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50),email VARCHAR(100),INDEX idx_name (name)
);
建表后添加
CREATE INDEX idx_name ON test.users(name)
(三) 查看索引
DESC 库名.表名; #查看表结构(简略)
SHOW INDEX FROM 表名\G # 查看索引详细信息#示例
DESC test.users;
SHOW INDEX FROM users\G
(四)删除索引
DROP INDEX 索引名 ON 库.表;#示例
DROP INDEX idx_name ON test.users;
(五)验证查询是否使用索引
EXPLAIN SELECT 查询语句;#示例
EXPLAIN SELECT * FROM test.users WHERE name = 'test';
- 关键字段说明:
type
:访问类型,ref
、range
、const
表示使用索引,ALL
表示全表扫描。key
:实际使用的索引名称。rows
:预估扫描行数,越少越好。Extra
:附加信息,如Using index
表示覆盖索引,Using filesort
表示需额外排序。
(六)索引使用建议
- 选择性高的字段优先建立索引(如用户ID、订单号)。
- 避免对低基数字段建索引(如性别、状态字段)。
- 联合索引字段顺序应遵循查询条件顺序。
- 避免在索引列上使用函数或表达式,会导致索引失效。
- 定期分析和优化索引,删除冗余或无效索引。
五、其它索引的使用
- 仅介绍创建示例其它部分类似普通索引的使用
(一)唯一索引
CREATE UNIQUE INDEX email_unique ON users(email);
(二)复合索引
CREATE INDEX name_age ON users(name, age);
(三)主键索引
ALTER TABLE users ADD PRIMARY KEY (id);
慢SQL分析与优化
一、定义
- 慢SQL是指执行时间超过预设阈值的SQL语句,这类查询通常执行效率低下,可能导致数据库响应变慢、资源占用过高,进而影响整个系统的稳定性和用户体验。
- 在MySQL中,默认将执行时间超过10秒的SQL定义为慢SQL。
二、常见原因
原因 | 说明 |
---|---|
查询未使用索引或索引失效 | 查询未利用索引或索引因某些原因失效,导致全表扫描 |
查询返回数据量过大 | 查询结果集过大,增加网络传输和内存消耗 |
SQL语句写法不合理 | 如使用了不合理的JOIN、子查询等,导致查询效率低下 |
数据库表结构设计不合理 | 表结构设计不当,如字段类型选择不当、表关联关系复杂等 |
数据库参数配置不当 | 数据库参数设置不合理,如缓冲区大小、连接数等 |
服务器硬件资源不足 | CPU、内存、磁盘IO等硬件资源不足,影响查询性能 |
三、影响
影响 | 说明 |
---|---|
系统响应变慢,用户体验下降 | 查询响应时间延长,用户等待时间增加 |
数据库连接池耗尽,导致系统崩溃 | 慢SQL占用连接时间过长,导致连接池资源耗尽 |
增加数据库服务器负载,影响其他业务 | 数据库服务器资源被大量占用,影响其他业务的正常运行 |
四、如何发现慢SQL
(一)开启慢查询日志
通过修改MySQL配置文件my.cnf
或使用命令行参数,开启慢查询日志功能,记录执行时间超过设定阈值的SQL语句。
- 修改配置文件
my.cnf
[mysqld] slow_query_log = 1 # 开启慢查询日志 long_query_time = 1 # 设置阈值(单位:秒) log_queries_not_using_indexes = 1 # 记录未使用索引的查询
- 命令行动态设置
#登录MySQL后执行SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; SET GLOBAL log_queries_not_using_indexes = 'ON';
(二)重启MySQL服务
systemctl restart mysqld
(三)查看慢日志文件路径
SHOW VARIABLES LIKE 'slow_query_log_file';
(四)分析慢查询日志
- 使用
mysqldumpslow
工具对慢查询日志进行分析,找出执行时间最长的SQL语句。mysqldumpslow -s t -t 10 /var/lib/mysql/mysql-slow.log # 按时间排序,显示前10条慢SQL # -s t 按查询时间排序 # -t 10 显示前10条记录
五、如何优化慢SQL
(一)优化查询语句
- 使用合适的索引:确保查询条件中的字段有索引,并避免索引失效。
- 避免全表扫描:尽量使用索引字段进行查询,减少扫描的数据量。
- 优化JOIN操作:确保JOIN字段有索引,避免使用复杂的嵌套JOIN。
- 限制返回数据量:使用
LIMIT
限制返回的记录数,避免返回过多数据。
(二)优化数据库结构
- 合理设计表结构:避免冗余字段,合理划分表结构。
- 使用合适的数据类型:选择合适的数据类型,减少存储空间和I/O开销。
- 归档历史数据:定期清理或归档旧数据,减少表的数据量。
(三)调整数据库配置
- 调整缓冲区大小:如
innodb_buffer_pool_size
、query_cache_size
等。 - 优化连接数:根据系统负载合理设置最大连接数
max_connections
。 - 启用查询缓存:对于读多写少的应用,可以开启查询缓存。
(四) 硬件和系统优化
- 升级硬件资源:增加CPU、内存、使用SSD等,提升系统性能。
- 优化操作系统参数:如文件描述符限制、内核参数等。
(五)使用性能分析工具
- EXPLAIN:分析SQL的执行计划,查看是否使用了索引。
- SHOW PROFILE:分析SQL执行过程中的资源消耗。
- Performance Schema:MySQL的性能分析工具,可以详细监控SQL执行情况。
六、优化示例
(一)对索引字段使用函数导致索引失效
优化前
SELECT * FROM orders WHERE DATE(create_time) = '2025-07-01';
问题分析
- 对
create_time
字段使用了DATE()
函数,导致 MySQL 无法使用该字段上的索引。 - 结果是全表扫描,查询性能差,尤其是在数据量大的情况下。
优化后
SELECT * FROM orders
WHERE create_time >= '2025-07-01' AND create_time < '2025-07-02';
优化说明
- 通过将函数操作转换为范围查询,避免对索引字段进行计算。
- 使 MySQL 能够利用
create_time
字段上的索引,显著减少扫描行数。
验证方法
EXPLAIN SELECT * FROM orders WHERE create_time >= '2025-07-01' AND create_time < '2025-07-02';
- 查看
type
是否为range
,key
是否为create_time
的索引名。 - 确认
rows
字段值大幅减少,表明索引生效。
(二)模糊查询导致索引失效
优化前
SELECT * FROM users WHERE name LIKE '%青竹%';
问题分析
- 使用了前模糊查询(
%青竹%
),导致 MySQL 无法使用name
字段上的索引。 - 结果是全表扫描,查询效率低。
优化后
SELECT * FROM users WHERE name LIKE '青竹%';
优化说明
- 将前模糊查询改为后模糊查询(青竹
%
),使 MySQL 能够利用name
字段上的索引。 - 适用于以特定前缀开头的搜索场景。
验证方法
EXPLAIN SELECT * FROM users WHERE name LIKE '青竹%';
- 查看
type
是否为range
,key
是否为name
的索引名。 - 确认
rows
字段值减少,表明索引生效。
(三)隐式类型转换导致索引失效
优化前
SELECT * FROM users WHERE phonenumber = 15212341234;
问题分析
phonenumber
字段为字符串类型,但查询时使用了数字类型,导致 MySQL 进行隐式类型转换。- 结果是索引失效,全表扫描。
优化后
SELECT * FROM users WHERE phonenumber = 15212341234;
优化说明
- 将查询条件中的数字类型改为字符串类型,避免隐式类型转换。
- 使 MySQL 能够利用
phone
字段上的索引。
验证方法
EXPLAIN SELECT * FROM users WHERE phonenumber = 15212341234;
- 查看
type
是否为ref
,key
是否为phonenumber
的索引名。 - 确认
rows
字段值减少,表明索引生效。
(四)联合索引未遵循最左前缀原则
优化前
SELECT * FROM users WHERE age = 24;
问题分析
- 存在联合索引
name_age(name, age)
,但查询条件中未包含name
字段。 - 结果是索引失效,全表扫描。
优化后
SELECT * FROM users WHERE name = '青竹' AND age = 24;
优化说明
- 在查询条件中加入
name
字段,遵循联合索引的最左前缀原则。 - 使 MySQL 能够利用
name_age
联合索引。
验证方法
EXPLAIN SELECT * FROM users WHERE name = '青竹' AND age = 24;
- 查看
type
是否为ref
,key
是否为name_age
。 - 确认
rows
字段值减少,表明索引生效。
优化案例
一、案例背景
- 某电商平台随着业务的快速发展,订单量不断攀升。
- 在日常运营中,订单统计报表查询功能频繁被使用,用于生成各类销售数据报表,为运营决策提供数据支持。
- 然而,随着订单数据量的急剧增长,当订单表中的数据量达到 600 万条时,报表查询的性能问题逐渐凸显。
- 具体表现为,以下用于统计用户订单总额和订单数量的 SQL 查询语句,执行时间超过 10 秒:
SELECT customer_id,COUNT(*) AS order_count,SUM(order_amount) AS total_order_amount FROM orders WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'AND status IN (1, 2, 3) GROUP BY customer_id ORDER BY total_order_amount DESC LIMIT 100;
二、优化过程
(一)问题定位
开启慢查询日志
- 通过修改 MySQL 配置文件
my.cnf
或使用命令行参数,开启慢查询日志功能,记录执行时间超过设定阈值的 SQL 语句。 - 修改配置文件
my.cnf
[mysqld] slow_query_log = 1 # 开启慢查询日志 slow_query_log_file = /var/log/mysql/slow.log # 指定日志文件路径 long_query_time = 1 # 设置阈值(单位:秒) log_queries_not_using_indexes = 1 # 记录未使用索引的查询
- 命令行动态设置
#登录 MySQL 后执行SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; SET GLOBAL log_queries_not_using_indexes = 'ON';
使用 EXPLAIN
分析执行计划
EXPLAIN
SELECT customer_id, COUNT(*), SUM(order_amount)
FROM orders
WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'AND status IN (1, 2, 3)
GROUP BY customer_id
ORDER BY total_order_amount DESC
LIMIT 100;
- 执行计划关键指标:
id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE orders ALL NULL NULL NULL NULL 6000000 10.00 Using where; Using filesort
- 问题点:
-
type: ALL
:表示全表扫描,未使用索引。 -
Using filesort
:表示需要额外排序,增加 CPU 和 I/O 开销。 -
Using temporary
:表示使用了临时表,常见于GROUP BY
操作。
-
(二)优化方案
索引优化
- 创建联合索引,覆盖
WHERE
条件和GROUP BY
字段:ALTER TABLE orders ADD INDEX idx_status_createtime_customerid (status, create_time, customer_id);
- 优化后执行计划
id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | orders | range | idx_status_createtime_customerid | idx_status_createtime_customerid | 6 | NULL | 150000 | 100.00 | Using where; Using index; Using filesort |
- 优化效果:
- 扫描行数从 600 万减少到 15 万。
- 使用覆盖索引(
Using index
),避免回表。 - 执行时间降至约 1.5 秒。
SQL 改写
- 原始写法在
GROUP BY
后需要对大量数据进行排序,性能较差。 - 优化思路是先缩小数据集再排序:
SELECT customer_id, order_count, total_order_amount FROM (SELECT customer_id,COUNT(*) AS order_count,SUM(order_amount) AS total_order_amount FROM orders WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'AND status IN (1, 2, 3)GROUP BY customer_id ) AS tmp ORDER BY total_order_amount DESC LIMIT 100;
- 优化效果:
- 避免对大结果集排序。
- 执行时间进一步降至约 0.9 秒。
归档历史数据
将超过 2 年的订单数据迁移到历史表,减少主表数据量:
-- 创建归档表
CREATE TABLE orders_archive LIKE orders;-- 迁移数据
INSERT INTO orders_archive
SELECT * FROM orders
WHERE create_time < '2023-01-01';-- 删除原表过期数据
DELETE FROM orders
WHERE create_time < '2023-01-01';
- 优化效果:
- 数据量从 600 万减少到 400 万。
- 查询时间稳定在 0.6 秒以内。
(三)最终优化组合
- 联合索引:
idx_status_createtime_customerid
- SQL 改写:先聚合后排序
- 数据归档:定期清理历史数据
- 参数调优:调整
my.cnf
中的相关参数[mysqld] tmp_table_size = 256M #定义MySQL内部临时表(MEMORY 表)的最大允许大小 #临时表的大小超过此值,MySQL会将其转储到磁盘,这会显著降低性能 #单位为字节,建议设为服务器内存的 1%-2%max_heap_table_size = 256M #限制用户显式创建的 MEMORY表的最大大小(通过 CREATE TABLE ... ENGINE=MEMORY)sort_buffer_size = 8M #定义每个连接用于排序操作(如 ORDER BY、DISTINCT、GROUP BY)的缓冲区大小 #排序操作会将数据加载到缓冲区,如果缓冲区不足,MySQL 会使用磁盘临时文件(filesort),导致性能下降
三、优化总结
优化手段 | 原理说明 | 适用场景 |
---|---|---|
联合索引 | 覆盖 WHERE 和 GROUP BY 字段,减少回表和排序开销 | 多条件过滤 + 分组统计查询 |
SQL 改写 | 减少中间结果集大小,避免全量排序 | 含 LIMIT 的分页或 TopN 查询 |
数据归档 | 降低单表数据量,减少索引树高度 | 时间序列数据的大表 |
参数调优 | 增加内存分配,避免磁盘临时表 | 复杂排序或分组操作 |
锁机制与并发优化
一、事务与锁机制
(一)SQL 语句类型
分类 | 全称 | 关键字 | 作用 |
---|---|---|---|
DDL | Data Definition Language | CREATE / ALTER / DROP | 定义或修改数据库、表、索引、视图等结构 |
DML | Data Manipulation Language | INSERT / UPDATE / DELETE | 对表中数据进行增、删、改 |
DQL | Data Query Language | SELECT / SHOW | 查询数据 |
DCL | Data Control Language | GRANT / REVOKE | 权限控制 |
TCL | Transaction Control Language | BEGIN / COMMIT / ROLLBACK / SAVEPOINT | 事务控制 |
(二)事务
-
作用域:仅针对 DML(
INSERT
、UPDATE
、DELETE
)。 -
定义:一组 DML 语句要么全部成功,要么全部失败,保证数据准确性。
(三)ACID 特性
特性 | 描述 |
---|---|
原子性 Atomicity | 事务内所有 DML 操作要么全部成功,要么全部回滚。 |
一致性 Consistency | 事务完成后,数据库从一种一致状态变为另一种一致状态。 |
隔离性 Isolation | 并发事务互不干扰,隔离级别控制可见性。 |
持久性 Durability | 一旦提交,数据永久生效,即使系统崩溃。 |
二、锁机制
锁类别 | 粒度 | 类型 | 典型语句 | 事务关联 |
---|---|---|---|---|
全局锁 | 实例级 | 只读 | FLUSH TABLES WITH READ LOCK | 一致性备份 |
表级锁 | 表级 | 读/写 | LOCK TABLES t WRITE | 离线批处理 |
行级锁 | 行级 | 共享/排他 | SELECT … FOR UPDATE | 并发 DML 事务 |
MDL | 表级(自动) | 元数据锁 | 隐式 | 防止 DDL 与 DML 冲突 |
(一)全局锁
介绍
- 全局锁通过
FLUSH TABLES WITH READ LOCK
对整个 MySQL 实例加锁,所有表瞬间变为只读,任何写事务或 DDL 都会被阻塞。
作用
- 用于需要“整库一致性快照”的场景:全库逻辑备份、主从切换、版本升级前的数据校验。
示例
#加全局读锁
FLUSH TABLES WITH READ LOCK;#在另一个终端执行一致性备份
mysqldump -u root -ptest --single-transaction test > backup.sql#备份完成后立即解锁
UNLOCK TABLES;
解释
FLUSH TABLES WITH READ LOCK
会刷新所有表并加全局读锁;此时所有写操作被阻塞。- 配合
mysqldump --single-transaction
可在 InnoDB 上实现“秒级”一致性备份,避免长时间锁库导致的业务写入中断。
(二)表级锁
介绍
- 表级锁通过
LOCK TABLES
显式锁定单张表,粒度比全局锁小,会话级显式锁。
作用
- 适用于离线批量导入、报表生成、表维护(OPTIMIZE/ALTER 前)等需要独占表的场景。
示例
#加表级写锁,确保 employees 表有主键索引,避免退化为全表锁
LOCK TABLES employees WRITE;#批量更新(其他会话对该表的读写均被阻塞)
UPDATE employees SET status = 4 WHERE create_time < '2025-07-01';#解锁
UNLOCK TABLES;
解释
LOCK TABLES employees WRITE
获得排他写锁,其他会话无法读写该表;若使用READ
则仅允许并发读。- 会话退出或执行
UNLOCK TABLES
后锁立即释放;脚本中务必保证解锁,避免锁表雪崩。
(三)行级锁
介绍
- InnoDB 存储引擎支持的最细粒度锁,仅锁定索引记录或记录间隙,不影响其他行。
作用
- 在高并发 OLTP 场景下保证数据一致性,防止脏读、幻读、更新丢失。
示例
#开启事务
START TRANSACTION;#对 id = 1 的行加排他锁,WHERE 条件必须命中索引,否则行锁会退化为表锁
SELECT * FROM employees WHERE id = 1 FOR UPDATE;#执行更新
UPDATE employees SET name = '青竹' WHERE id = 1;#提交事务,锁自动释放
COMMIT;
解释
FOR UPDATE
对主键 id = 1 的记录加排他锁,其他事务无法修改或加锁该行。- 若 WHERE 条件无法走索引,会退化为表级锁,因此务必确保有合适索引;长事务会阻塞后续操作。
(四)元数据锁
介绍
- MDL 是 MySQL 5.5+ 自动维护的表级锁,用于保护表结构一致性,防止 DDL 与 DML 并发冲突。
作用
- 任何 DML 语句都会隐式获取 MDL 共享锁;DDL 需要排他 MDL。
- 长事务未提交时,DDL 会被阻塞,出现 “Waiting for table metadata lock”。
示例
- 会话 A:
START TRANSACTION; SELECT * FROM employees WHERE id = 1 FOR UPDATE; #此时持有 employees 的 MDL 共享锁
- 会话 B:
ALTER TABLE employees ADD COLUMN extra VARCHAR(20); #等待 MDL 排他锁,被阻塞
- 查看锁等待:
SELECT * FROM performance_schema.metadata_locks; SHOW PROCESSLIST;
解释
- 会话 A 未提交,导致会话 B 的 ALTER 无法获得排他 MDL。
- 解决:缩短事务、提交/回滚后再执行 DDL,或设置
lock_wait_timeout
避免无限等待。
三、锁机制在MySQL优化中的价值
- 备份窗口最小化
- 全局锁 +
--single-transaction
组合,将一致性备份时间从分钟级降到秒级,降低业务抖动。
- 全局锁 +
- 批量任务提速
- 表级写锁在低峰期一次性处理百万级记录,避免逐行锁带来的大量上下文切换。
- 并发冲突降级
- 行级锁保证热点数据高并发读写;表级锁用于冷数据批量维护,两者互补。
- DDL 平滑执行
- 通过监控 MDL 等待队列,提前结束长事务,使 ALTER TABLE 在业务低峰期 10 秒内完成,避免高峰期锁表雪崩。