简介:本资源为MySQL 5.7官方中文文档的完整离线版,面向数据库初学者、运维工程师及后端开发人员,解决在线查阅不便、网络受限或需快速检索核心特性的实际需求。压缩包共785个文件,主体为768个HTML页面(涵盖安装配置、SQL语法、InnoDB引擎、JSON支持、GTID复制、性能Schema监控等全部模块),辅以12张说明性示意图(JPG)、1个样式表(CSS)及必要电子书元数据文件(NCX/OPF/XML等),结构完整、可直接双击浏览,总大小仅8.79MB,轻量便携。已有3687人学习下载,内容严格对应MySQL 5.7正式版功能体系,包含事务机制演进、查询优化器改进细节、列式存储适配说明、安全加固配置项等深度技术要点,是系统掌握该经典稳定版本不可替代的权威参考。
1. MySQL 5.7 中文文档:不是“翻译版说明书”,而是能直接查、能立刻改、能避开锁表翻车的实战手边书
你有没有试过在生产环境执行一条ALTER TABLE,结果发现整个库卡住三分钟,监控告警狂响,而你翻遍官网英文页却卡在ALGORITHM=INPLACE和LOCK=NONE的嵌套条件里?这不是玄学,是 MySQL 5.7 原生支持在线 DDL 的能力没被真正“唤醒”——而唤醒它的钥匙,就藏在那份被很多人当成摆设的《MySQL 5.7 中文文档》里。它不是 PDF 打印版的镜像复刻,而是由社区核心贡献者逐章校对、术语统一、示例重跑、错误勘正后的可执行知识体。它覆盖从my.cnf里innodb_buffer_pool_instances的取值边界(小于 1 或大于 64 会静默失效),到performance_schema中events_statements_history_long表的默认保留条数(10000 条,但超量后不报错只丢旧数据)这类血泪经验。适合正在维护 5.7 线上集群的 DBA、需要写稳定 SQL 的后端工程师、以及刚从 8.0 回退适配老系统的开发同学——因为 5.7 的权限模型、JSON 函数行为、半同步复制握手逻辑,和后续版本有实质性断裂。
2. 文档结构与核心模块定位:按问题类型反向索引,而不是从第一页开始读
MySQL 官方文档以“手册式”组织,但真实排障从来不是线性阅读。一份合格的中文文档,必须支持你用“症状→模块→参数→验证”四步闭环。下面这张表,是我把整份 5.7 中文文档按高频问题域重新映射后的导航图。它不替代目录,而是告诉你:当你的服务突然变慢、连接数暴涨、主从延迟飙升时,该跳转到哪一章、盯住哪几个配置项、用什么 SQL 快速验证。
| 问题现象 | 对应文档章节(中文版页码锚点) | 关键参数/命令 | 验证方式 |
|---|---|---|---|
SHOW PROCESSLIST里大量Waiting for table metadata lock | 第 8.11.4 节 “元数据锁” + 附录 C.5 “锁等待诊断” | innodb_lock_wait_timeout,lock_wait_timeout | SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_TYPE='TABLE' AND LOCK_STATUS='PENDING'; |
主从延迟持续 > 30 秒,Seconds_Behind_Master持续增长 | 第 17.4.1.39 节 “复制延迟原因分析” + 第 17.1.6.3 节 “基于行的复制事件大小限制” | binlog_row_image,slave_parallel_workers | SHOW SLAVE STATUS\G中Exec_Master_Log_Pos与Read_Master_Log_Pos差值是否持续扩大;SELECT EVENT_INFO FROM performance_schema.events_statements_current WHERE SQL_TEXT LIKE '%INSERT%';查大事务 |
mysqld启动失败,日志报InnoDB: Unable to lock ./ibdata1 error 11 | 第 14.21.2 节 “InnoDB 启动故障排查” + 第 5.1.8 节 “系统变量作用域” | innodb_data_home_dir,innodb_data_file_path,innodb_force_recovery | ls -l /var/lib/mysql/ibdata1确认文件权限;strace -e trace=openat,open mysql_install_db 2>&1 | grep ibdata观察打开路径 |
应用报Packet for query is too large,但max_allowed_packet已设为 1G | 第 5.1.12 节 “服务器系统变量” + 第 12.19 节 “字符串函数限制” | max_allowed_packet,net_buffer_length,wait_timeout | SELECT @@max_allowed_packet, @@net_buffer_length;;检查客户端连接时是否显式设置了更小的max_allowed_packet(如 JDBC URL 中?maxAllowedPacket=67108864) |
EXPLAIN显示type=ALL,但表有索引且WHERE条件明确 | 第 8.2.1 节 “EXPLAIN 输出格式” + 第 8.3.7 节 “索引合并优化” | optimizer_switch,use_index_merge,range_optimizer_max_mem_size | SELECT @@optimizer_switch;;强制关闭索引合并测试:SET SESSION optimizer_switch='index_merge=off'; EXPLAIN SELECT ...; |
提示:中文文档中所有带
mysql>提示符的 SQL 示例,均已在 MySQL 5.7.39 社区版实测通过。但注意——部分示例依赖sysschema(需手动安装),而sys在 5.7 中默认不启用。安装命令为:mysql -u root -p < /usr/share/mysql/sys_schema.sql(路径依实际安装包而定)。未装sys时,performance_schema相关查询仍可用,只是缺少高层视图封装。
2.1 为什么必须用 5.7 专属中文文档,而不是通用翻译或 8.0 文档降级?
很多团队图省事,直接拿 MySQL 8.0 英文文档机翻,或用 5.7 英文版+浏览器插件翻译。这在三个关键点上会致命:
- 权限模型断裂:5.7 的
CREATE USER语法不支持IDENTIFIED WITH插件指定(那是 8.0 引入的),但 8.0 文档里所有用户创建示例都含此子句。若照搬,5.7 会报ERROR 1064 (42000): You have an error in your SQL syntax,而错误位置指向WITH,新人极易误判为 SQL 拼写错误。 - JSON 函数行为差异:5.7.8 引入
JSON_EXTRACT(),但JSON_TABLE()是 8.0.4 才有的。中文文档第 12.16.3 节明确标注“仅限 MySQL 8.0 及以上”,并给出 5.7 下等效的JSON_EXTRACT(json_col, '$.key')+CAST(... AS UNSIGNED)组合方案。而通用翻译文档常把 8.0 新函数混入 5.7 章节,导致代码无法运行。 - InnoDB 参数废弃逻辑:5.7.21 开始,
innodb_file_per_table默认为ON,但innodb_file_format和innodb_large_prefix在 5.7.7 后已废弃(文档第 14.13 节注明“Deprecated as of MySQL 5.7.7”)。若参考 5.6 文档或未更新的博客,仍配置这些参数,MySQL 不报错但完全忽略,造成预期外的表空间管理失效。
我一般会在新接手一个 5.7 集群时,先执行SELECT VERSION();确认小版本号,再打开对应小版本的中文文档 PDF(如mysql-5.7.39-refman-zh.pdf),用 Adobe Acrobat 的“查找全部”功能搜索关键词,而非依赖目录树——因为真实问题往往跨章节,比如“死锁”涉及第 14.7.5 节(InnoDB 死锁检测)、第 8.11.2 节(锁兼容矩阵)、第 13.7.5.30 节(SHOW ENGINE INNODB STATUS解析),三处信息缺一不可。
2.2 如何把文档从“查手册”变成“写脚本”的依据?
文档的价值,最终要落到自动化上。比如,线上某张订单表t_order近期频繁出现Lock wait timeout exceeded,你想批量检查所有WHERE status = ?的 UPDATE 是否缺失索引。这时不能靠肉眼扫SHOW CREATE TABLE,而要写 SQL 从information_schema中提取模式,再比对文档定义的“索引使用规则”。
以下脚本直接依据中文文档第 8.3.1 节“MySQL 如何使用索引”的判定逻辑编写:
-- 检查 t_order 表中所有 WHERE 条件含 status 字段的 UPDATE 语句,是否命中索引 SELECT DIGEST_TEXT, COUNT_STAR AS exec_count, SUM_TIMER_WAIT/1000000000000 AS avg_time_sec, -- 文档第 8.3.1 节指出:WHERE 条件中对索引列使用函数会导致索引失效 CASE WHEN DIGEST_TEXT REGEXP 'UPDATE.*t_order.*SET.*WHERE.*status.*[+\\-\\*/].*' THEN '⚠️ 算术运算,索引失效' WHEN DIGEST_TEXT REGEXP 'UPDATE.*t_order.*SET.*WHERE.*UPPER\\(status\\)' THEN '⚠️ 函数操作,索引失效' WHEN DIGEST_TEXT REGEXP 'UPDATE.*t_order.*SET.*WHERE.*status.*LIKE.*%' THEN '✅ LIKE 前缀匹配,可能有效' ELSE '🔍 需人工确认' END AS index_usage_hint FROM performance_schema.events_statements_summary_by_digest WHERE DIGEST_TEXT LIKE 'UPDATE%t_order%status%' AND LAST_SEEN > DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY SUM_TIMER_WAIT DESC LIMIT 20;这段 SQL 的每一行判断,都对应中文文档中明确写出的索引使用边界。例如UPPER(status)的判断,源自文档第 8.3.1 节原文:“如果在索引列上应用了函数或表达式,则 MySQL 无法使用该索引进行查找”。而LIKE的前缀匹配提示,则来自同一节的补充说明:“LIKE 'abc%'可以使用索引,但LIKE '%abc'不能”。这种将文档条款直接转化为 SQL 逻辑的能力,才是中文文档作为“可执行知识”的核心价值。
3. 配置调优实战:从my.cnf十个关键参数到performance_schema实时观测
调优不是调数字,而是理解参数背后的资源契约。MySQL 5.7 的my.cnf里,十个参数决定了 80% 的性能表现。但它们的取值不是拍脑袋,而是受硬件、业务特征、文档定义的硬性约束所框定。下面我以某电商订单库(日均写入 200 万,峰值 QPS 1200)为例,展示如何结合中文文档完成一次闭环调优。
3.1innodb_buffer_pool_size:不是越大越好,而是要避开“内存抖动陷阱”
文档第 14.8.3.1 节明确指出:“innodb_buffer_pool_size应设置为物理内存的 50%~75%,但必须确保操作系统仍有足够内存运行其他进程(如备份工具、监控 agent)”。这看似常识,但实操中常被忽视。
某次我们把一台 64G 内存的 DB 服务器innodb_buffer_pool_size设为50G,结果每天凌晨 3 点定时 mysqldump 备份时,系统 OOM killer 杀掉 mysqld 进程。查dmesg日志发现:
Out of memory: Kill process 12345 (mysqld) score 892 or sacrifice child原因在于:mysqldump默认单线程全表导出,会触发大量磁盘读,而innodb_buffer_pool已占满内存,OS 缓存无空间,导致内存压力激增。
解决方案:
- 按文档建议,将
innodb_buffer_pool_size降至42G(64G × 65%),留出 22G 给 OS 及其他进程; - 同时在备份脚本中添加
--single-transaction --skip-triggers --no-autocommit,减少锁和事务开销; - 最关键的是,启用
innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup(文档第 14.8.3.6 节),让热数据在重启后快速加载,避免冷启动抖动。
注意:
innodb_buffer_pool_size修改后必须重启 mysqld 生效,且重启期间服务中断。若需在线调整(5.7.5+ 支持),需用SET GLOBAL innodb_buffer_pool_size = 42949672960;,但文档第 14.8.3.1 节强调:“在线调整仅在 buffer pool 总大小变化不超过 1GB 时可靠,大幅调整仍推荐重启”。
3.2innodb_log_file_size与innodb_log_buffer_size:WAL 日志的吞吐瓶颈拆解
这是最容易被误配的一组参数。文档第 14.4.6 节定义:innodb_log_file_size是每个 redo log 文件的大小,innodb_log_buffer_size是内存中用于暂存 redo 日志的缓冲区。
常见错误是把两者设为相同值(如都设为 256M),导致严重性能下降。真相是:
innodb_log_buffer_size应足够容纳单个大事务的 redo 日志(通常 8M~16M 足够,文档建议“一般无需超过 16MB”);innodb_log_file_size则决定 checkpoint 频率——太小则频繁刷盘,太大则崩溃恢复慢。文档第 14.4.6.1 节给出公式:innodb_log_file_size ≈ (innodb_buffer_pool_size × 0.25) / innodb_log_files_in_group。
我们线上innodb_buffer_pool_size=42G,innodb_log_files_in_group=2,按公式计算得innodb_log_file_size ≈ 5.25G。但文档第 14.4.6.2 节又警告:“innodb_log_file_size最大值不应超过 4G(某些文件系统限制)”。于是我们取4G,并接受稍高的 checkpoint 频率。
调整步骤(必须停机):
# 1. 先安全关闭 MySQL sudo systemctl stop mysqld # 2. 备份原 redo log 文件(至关重要!) sudo cp /var/lib/mysql/ib_logfile* /backup/ # 3. 修改 my.cnf echo "innodb_log_file_size = 4294967296" | sudo tee -a /etc/my.cnf # 4. 启动 MySQL(首次启动会自动重建 redo log) sudo systemctl start mysqld提示:修改
innodb_log_file_size后首次启动,MySQL 会删除旧ib_logfile*并创建新文件。若启动失败,立即停止,并从备份恢复原文件——否则数据库无法启动。
3.3 用performance_schema实时验证调优效果:不只是看SHOW STATUS
文档第 25 章完整定义了performance_schema的 87 张表。但真正高频使用的只有 5 张。我们用它们构建一个 5 分钟快速验证链:
-- 1. 看 buffer pool 命中率(文档第 14.8.3.4 节:理想 > 99.5%) SELECT (SUM(IF(variable_name = 'Innodb_buffer_pool_read_requests', variable_value, 0)) - SUM(IF(variable_name = 'Innodb_buffer_pool_reads', variable_value, 0))) * 100.0 / SUM(IF(variable_name = 'Innodb_buffer_pool_read_requests', variable_value, 0)) AS hit_ratio_pct FROM information_schema.global_status WHERE variable_name IN ('Innodb_buffer_pool_read_requests', 'Innodb_buffer_pool_reads'); -- 2. 看当前活跃事务锁等待(文档第 14.7.5.30 节:`SHOW ENGINE INNODB STATUS` 的结构化替代) SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread, r.trx_query waiting_query, b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread, b.trx_query blocking_query FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; -- 3. 看最近 1 小时最耗时的 10 条语句(文档第 25.12.12 节:`events_statements_summary_by_digest`) SELECT DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT/1000000000000 AS avg_time_sec, SUM_ROWS_AFFECTED FROM performance_schema.events_statements_summary_by_digest WHERE LAST_SEEN > DATE_SUB(NOW(), INTERVAL 1 HOUR) ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;这三组查询,每一条都直指文档中定义的核心指标。它们不是“看看就行”,而是调优闭环的终点——如果hit_ratio_pct低于 99%,说明innodb_buffer_pool_size还不够;如果第二条返回多行,说明锁竞争未缓解;如果第三条里出现UPDATE t_order SET status=? WHERE id=?占比过高,那就要回到 2.2 节的索引检查脚本去深挖。
4. 常见问题排查:五个真实翻车现场与文档定位指南
文档的价值,在于它能让你在深夜告警时,30 秒内定位到根本原因。以下是我在多个 5.7 集群中踩过的坑,每一条都标注了对应的中文文档章节和精确描述,避免你重复交学费。
4.1 现象:mysqld启动后立即退出,错误日志只有一行Aborted
原因:my.cnf中datadir路径指向了一个空目录,且未执行mysql_install_db初始化。MySQL 5.7.6+ 已弃用mysql_install_db,改用mysqld --initialize(文档第 2.10.1.1 节)。但很多运维脚本仍沿用旧命令,导致初始化失败,而错误日志不输出具体原因。
解决:
- 删除
datadir下所有文件; - 执行
sudo mysqld --initialize --user=mysql --datadir=/var/lib/mysql; - 查看临时生成的 root 密码:
sudo grep 'temporary password' /var/log/mysqld.log; - 启动服务:
sudo systemctl start mysqld。
4.2 现象:主从复制中断,SHOW SLAVE STATUS\G中Seconds_Behind_Master: NULL,Slave_SQL_Running_State: Waiting for master to send event
原因:主库binlog_format设为STATEMENT,但从库执行了包含UUID()、NOW()等非确定性函数的语句(文档第 17.1.2 节:“STATEMENT 格式下,非确定性函数可能导致主从数据不一致,MySQL 5.7 默认拒绝执行”)。
解决:
- 主库执行
SET GLOBAL binlog_format = 'ROW';; - 从库执行
STOP SLAVE; START SLAVE;; - 长期方案:在
my.cnf中统一配置binlog_format=ROW(文档第 5.1.12 节)。
4.3 现象:执行ALTER TABLE t_user ADD COLUMN phone VARCHAR(20)耗时 15 分钟,期间所有对该表的查询被阻塞
原因:未启用在线 DDL。5.7 默认支持ALGORITHM=INPLACE,但LOCK=NONE需满足严格条件(文档第 14.13.3 节:“添加列必须是非空且有默认值,或允许 NULL”)。我们建表时phone定义为VARCHAR(20) NOT NULL,触发了拷表。
解决:
- 改为
ADD COLUMN phone VARCHAR(20) NULL DEFAULT NULL; - 或分两步:先
ADD COLUMN phone VARCHAR(20) NULL,再ALTER TABLE t_user MODIFY COLUMN phone VARCHAR(20) NOT NULL DEFAULT ''(第二步仍需锁表,但时间极短)。
4.4 现象:SELECT JSON_EXTRACT(json_col, '$.name') FROM t_log返回NULL,但json_col字段内容确认含{"name": "Alice"}
原因:json_col字段类型为TEXT而非JSON。5.7 要求 JSON 函数的输入必须是JSON类型字段,否则返回NULL(文档第 12.16.1 节:“JSON_EXTRACT()的第一个参数必须是有效的 JSON 值,TEXT类型需先用CAST()转换”)。
解决:
- 方案一(推荐):
ALTER TABLE t_log MODIFY COLUMN json_col JSON;; - 方案二(兼容旧结构):
SELECT JSON_EXTRACT(CAST(json_col AS JSON), '$.name') FROM t_log;。
4.5 现象:GRANT SELECT ON db1.* TO 'app'@'%'执行成功,但应用连接后报Access denied for user 'app'@'10.0.1.5'
原因:MySQL 用户认证是“用户名+主机名”联合匹配。'app'@'%'不匹配app'@'10.0.1.5',因为%不匹配 IP 地址(文档第 6.2.4 节:“%匹配任意主机名,但不匹配 IP 地址;要匹配 IP,需显式指定'app'@'10.0.1.%'或'app'@'10.0.1.5'”)。
解决:
- 创建精确用户:
CREATE USER 'app'@'10.0.1.5' IDENTIFIED BY 'pwd'; GRANT SELECT ON db1.* TO 'app'@'10.0.1.5';; - 或使用主机名通配:
CREATE USER 'app'@'%.company.com' IDENTIFIED BY 'pwd';(需 DNS 可解析)。
5. 高级技巧:用文档定义的“未公开行为”绕过限制,实现零停机扩容
MySQL 5.7 的文档里,藏着一些未被高亮、但被明确定义的“灰色能力”。它们不是 Bug,而是设计时预留的弹性接口。善用它们,能解决那些看似必须停机的问题。下面这个“零停机增加从库”的技巧,就是从文档第 17.1.6.3 节“基于行的复制事件大小限制”和第 17.4.1.39 节“复制延迟原因分析”中推导出来的。
5.1 场景还原:线上主库负载已达 85%,需紧急加一台从库分担读流量,但mysqldump全库导出会压垮主库
常规做法是mysqldump --single-transaction,但它会对所有表加SELECT锁(虽不阻塞写,但会拖慢SELECT),在高并发读场景下不可行。而文档第 17.1.6.3 节提到:“基于行的复制(RBR)下,主库只记录变更的行数据,不记录 SQL 语句本身;因此,只要从库的relay_log能追上主库的binlog,就能保证数据一致”。
这意味着:我们可以不 dump 主库,而是 dump 一台已存在的、延迟可控的从库,再用其数据启动新从库。因为 dump 从库不会对主库产生任何压力。
5.2 操作步骤(全程无需主库停机)
前提:已有从库slave1,Seconds_Behind_Master < 5,且开启log_slave_updates(文档第 17.1.6.1 节要求,否则无法作为中间主库)。
# 步骤 1:在 slave1 上,获取当前 relay log 位置(即它已执行到主库的哪个 binlog 点) mysql -u root -p -e "SHOW SLAVE STATUS\G" | grep -E "(Relay_Master_Log_File|Exec_Master_Log_Pos)" # 输出示例:Relay_Master_Log_File: mysql-bin.000123, Exec_Master_Log_Pos: 123456789 # 步骤 2:在 slave1 上执行 dump(此时主库完全无感知) mysqldump --all-databases --single-transaction --routines --triggers \ --master-data=2 --flush-logs --set-gtid-purged=OFF \ -u root -p > /backup/slave1_full_$(date +%Y%m%d).sql # 步骤 3:将 dump 文件传到新从库服务器,并导入 mysql -u root -p < /backup/slave1_full_20240601.sql # 步骤 4:关键一步——在新从库上,设置 CHANGE MASTER TO 指向原始主库, # 且起始位置为 slave1 当前执行到的位置(即步骤 1 获取的值) mysql -u root -p -e " CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='repl', MASTER_PASSWORD='repl_pwd', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000123', MASTER_LOG_POS=123456789, MASTER_AUTO_POSITION=0; START SLAVE;"原理说明:因为
slave1是从主库实时同步的,它Exec_Master_Log_Pos对应的 binlog 位置,就是主库当前最新的、已提交事务的位置。新从库从该位置开始拉取 binlog,天然与主库保持一致。文档第 17.4.1.39 节明确:“只要从库的MASTER_LOG_POS设置为一个有效的、主库 binlog 中存在的位置,复制即可正确启动”。
5.3 验证与收尾:用文档定义的指标确认一致性
不能只信START SLAVE成功。必须用文档第 17.1.6.3 节定义的“复制一致性黄金指标”验证:
# 在新从库上执行(文档第 17.1.6.3 节:对比主从的 GTID_EXECUTED) -- 1. 查主库 GTID_EXECUTED(需在主库执行) SELECT @@global.gtid_executed; -- 2. 查新从库 GTID_EXECUTED(需在新从库执行) SELECT @@global.gtid_executed; -- 3. 二者必须完全相等,才代表数据完全一致 -- 若不等,说明新从库还没追上,继续等待并轮询同时,监控Seconds_Behind_Master是否稳定在0,且Slave_IO_Running和Slave_SQL_Running均为Yes(文档第 17.1.6.1 节定义的健康状态)。
从那以后我每次加从库,都强制走一遍这个“dump 从库+精准定位”流程。它把原本 2 小时的停机窗口,压缩到 15 分钟的配置时间,且主库 CPU 曲线毫无波动。文档里那些看似枯燥的“复制位置”、“GTID 执行集”定义,原来就是我们对抗高负载的盾牌。
希望帮到你。
本文还有配套的精品资源,点击获取