MySQL主从原理是高可用架构的基石。
本书彻底地分析了MySQL主从原理。
本书是作者多年来研究MySQL原理和实践的成果。
MySQL从业人员应人手一本备在身边,以防不时之需。
在超大规模流量的分布式系统环境下,无论是从系统性能的角度,还是从数据安全性的角度,掌握MySQL主从原理,都是当下技术人员的必备基本功。MySQL主从原理是高可用架构的基石,即便是MGR这种集群架构也可以看到主从的影子。要解决一个问题或者故障,最快的方式就是了解它的原理,快速定位问题。本书从源码层面抽丝剥茧般地描述MySQL主从原理,全面地介绍了GTID相关的知识点,并解析了主要Event的生成、作用和格式,以及线程的初步知识、MDL LOCK、排序等热门话题和主从相关的案例。无论是MySQL DBA和MySQL源码爱好者,还是刚进入数据库行业的小白读者,通过阅读本书,都能通过源码级分析,更好地理解和使用MySQL主从复制技术。
高鹏(网名八怪),现任中亦安图科技有限公司数据库专家,2008年开始从事Oracle/MySQL相关工作,Oracle OCM、MySQL源码爱好者,知数堂8期学员。有丰富的数据库性能调优、故障诊断经验。
第1章 GTID 11.1 GTID的基本概念 11.1.1 GTID的作用 11.1.2 GTID的基本表示 11.1.3 server_uuid的生成 21.1.4 GTID的生成 21.1.5 GTID_EVENT和PREVIOUS_GTIDS_LOG_EVENT简介 31.1.6 gtid_executed表的作用 41.2 mysql.gtid_executed表、gtid_executed变量、gtid_purged变量的修改时机 51.2.1 定义 51.2.2 主库修改时机 71.2.3 从库修改时机 81.2.4 通用修改时机 101.2.5 通用修改时机源码函数简析 101.3 GTID模块初始化简介和参数binlog_gtid_simple_recovery 111.3.1 GTID模块初始化流程图 121.3.2 步骤解析 131.4 GTID中的运维 161.4.1 跳过一个事务 171.4.2 mysqldump导出行为的改变 171.4.3 搭建GTID AUTO_POSITION MODE的主从 181.4.4 主从切换 201.4.5 参数gitd_mode的含义 211.4.6 在线开启GTID 211.4.7 离线开启GTID 221.4.8 开启GTID的注意事项 231.4.9 统计值ONGOING_ANONYMOUS_TRANSACTION_COUNT的变更时机 231.4.10 设置MASTER_AUTO_POSITION = 1的影响 251.4.11 离线开启GTID丢失数据的测试 25第2章 Event 282.1 binary log Event 的总体格式 282.1.1 引言 282.1.2 binary log综述 282.1.3 Event的总体格式 292.1.4 Event header和Event footer 292.1.5 具体解析 302.1.6 本书涉及的Event类型 312.2 重点Event之FORMAT_DESCRIPTION_EVENT和PREVIOUS_GTIDS_LOG_EVENT 322.2.1 FORMAT_DESCRIPTION_EVENT 322.2.2 PREVIOUS_GTIDS_LOG_EVENT 352.3 重点Event之GTID_EVENT 392.3.1 GTID_EVENT的作用 392.3.2 源码重要接口 402.3.3 主体格式 402.3.4 简单解析 412.3.5 生成时机 412.3.6 ANONYMOUS_GTID_EVENT 412.3.7 GTID的三种模式 422.4 重点Event之QUERY_EVENT和MAP_EVENT 432.4.1 QUERY_EVENT 432.4.2 MAP_EVENT 462.5 重点Event之WRITE_EVENT和DELETE_EVENT 512.5.1 WRITE_EVENT 512.5.2 DELETE_EVENT 572.6 重点Event之UPDATE_EVENT和XID_EVENT 612.6.1 UPDATE_ROWS_EVENT 612.6.2 XID_EVENT 662.7 参数binlog_row_image的影响 682.7.1 参数影响 682.7.2 过滤方式 702.7.3 DML Event中的标识 702.8 巧用Event发现问题 732.8.1 工具简介 732.8.2 分析长期未提交的事务 742.8.3 分析大事务 752.8.4 分析binary log中Event的生成速度 752.8.5 分析每个表生成了多少个DML Event 752.8.6 工具展示 75第3章 主库 793.1 binlog cache简介 793.1.1 binlog cache综述 793.1.2 使用binlog cache的流程 803.1.3 参数binlog_cache_size的作用及其初始化 803.1.4 临时文件的分配和使用 813.1.5 参数max_binlog_cache_size的作用 823.1.6 如何观察到临时文件 823.2 事务Event的生成和写入流程 833.2.1 流程综述 833.2.2 删除阶段流程 853.2.3 提交阶段流程 853.2.4 两个注意点 863.3 MySQL层事务提交流程简析 863.3.1 参数设置 863.3.2 总体流程图 873.3.3 步骤解析第一阶段 903.3.4 步骤解析第二阶段(FLUSH阶段) 903.3.5 步骤解析第三阶段(SYNC阶段) 923.3.6 步骤解析第四阶段(COMMIT阶段) 933.3.7 步骤解析第五阶段 943.3.8 提交阶段的注意点 953.4 基于WRITESET的并行复制方式 953.4.1 奇怪的last commit 963.4.2 WRITESET是什么 963.4.3 WRITESET的生成 973.4.4 add_pke函数的流程 983.4.5 WRITESET设置对last commit的处理方式 993.4.6 WRITESET的历史MAP 1003.4.7 WRITESET的并行复制对last commit的处理流程 1003.4.8 WRITESET_SESSION的方式 1043.4.9 关于参数binlog_transaction_dependency_history_size的说明 1043.4.10 没有主键的情况 1043.4.11 为什么同一个session执行的事务能生成同样的last commit 1053.4.12 WRITESET并行复制方式的优缺点 1053.5 主库的DUMP线程 1063.5.1 POSITION MODE和GTID AUTO_POSITION MODE的不同点 1063.5.2 流程图 1083.5.3 步骤解析 1093.5.4 重点说明 1123.6 DUMP线程查找和过滤GTID的基本算法 1133.6.1 环境假设 1133.6.2 检查从库的GTID是否大于主库的GTID 1143.6.3 检查需要的binary log是否已经清理 1143.6.4 实际扫描binary log 1153.6.5 GTID过滤 115第4章 从库 1174.1 从库MTS多线程并行回放(一) 1174.1.1 MTS综述 1174.1.2 协调线程的分发机制 1184.1.3 步骤解析 1204.1.4 并行回放判定一例 1244.2 从库MTS多线程并行回放(二) 1264.2.1 工作线程执行Event 1264.2.2 MTS检查点中的重要概念 1274.2.3 MTS中执行检查点的流程 1324.2.4 MTS的关键点 1364.3 MTS中的“gap”测试和参数lave_preserve_commit_ order 1364.3.1 MTS中的“gap”测试 1364.3.2 参数slave_preserve_commit_order的影响 1384.4 从库的I/O线程 1394.4.1 引入 1394.4.2 I/O线程的启动流程图 1404.4.3 流程解析 1424.5 从库的SQL线程(MTS协调线程)和参数sql_slave_skip_counter 1464.5.1 SQL线程的功能 1464.5.2 流程图 1464.5.3 重要步骤说明 1484.5.4 各个Event做了什么 1514.6 从库数据的查找和参数slave_rows_search_algorithms 1534.6.1 从一个例子出发 1534.6.2 确认查找数据的方式 1564.6.3 ROW_LOOKUP_HASH_SCAN方式的数据查找 1594.6.4 从库数据查找的要点 1614.7 从库的关闭和异常恢复流程 1624.7.1 正常的stop slave流程 1624.7.2 stop slave为什么会慢 1634.7.3 从库启动需要读取的信息 1644.7.4 关于repository表的事务性 1654.7.5 相关参数 1664.7.6 恢复流程 1674.8 安全高效的从库设置 1704.8.1 从库参数设置建议 1704.8.2 单SQL线程模式 1714.8.3 MTS 1744.8.4 一个非安全设置的例子 1764.8.5 参数sync_relay_log的影响 1774.9 从库Seconds_Behind_Master的计算方式 1774.9.1 Seconds_Behind_Master的计算方式 1784.9.2 影响Seconds_Behind_Master的因素 1784.9.3 不同操作计算延迟的方式 1814.9.4 MTS中Seconds_Behind_Master计算误差测试 1814.9.5 手动修改系统时间导致Seconds_Behind_Master为0 1834.10 Seconds_Behind_Master延迟场景归纳 1854.10.1 延迟场景 1854.10.2 相关测试 1864.10.3 延迟诊断的方法论 189第5章 案例解析 1905.1 线程简介和MySQL调试环境搭建 1905.1.1 线程简介 1905.1.2 PID、LWP ID、Thread TID 1925.1.3 MySQL线程和系统LWP ID的关系 1935.1.4 调试环境的搭建 1945.1.5 调试环境的使用 1975.2 MySQL排序详细解析 1985.2.1 为什么要讨论排序 1985.2.2 从一个问题出发 1995.2.3 测试案例 2005.2.4 阶段1:确认排序字段及顺序 2025.2.5 阶段2:计算sort字段长度 2025.2.6 阶段3:计算额外字段的空间 2035.2.7 阶段4:确认每行的长度 2055.2.8 阶段5:确认最大内存分配 2065.2.9 阶段6:读取数据进行内存排序 2075.2.10 阶段7:排序方式总结输出 2105.2.11 阶段8:进行最终排序 2115.2.12 排序的其他问题 2125.2.13 使用OPTIMIZER_TRACE查看排序信息 2145.2.14 回到问题本身 2155.2.15 答疑 2175.3 MySQL中的MDL Lock简介 2195.3.1 MDL Lock综述 2195.3.2 重要数据结构和概念 2205.3.3 为MDL Lock增加打印函数 2255.3.4 在合适的位置增加打印函数 2275.3.5 常见MDL Lock类型的加锁测试 2295.4 奇怪的FTWRL堵塞案例 2375.4.1 两个不同的现象 2375.4.2 sleep 函数生效点 2395.4.3 FTWRL做了什么工作 2405.4.4 例5-3步骤解析 2425.4.5 例5-4步骤解析 2435.4.6 FTWRL堵塞和被堵塞的简单总结 2445.5 产生大量小relay log故障案例 2455.5.1 案例现象 2455.5.2 参数slave_net_timeout分析 2455.5.3 原因剖析 2465.5.4 案例模拟 2465.5.5 实现方式 2485.6 从库system lock原因简析 2505.6.1 binary log的写入时间和Event中的时间 2505.6.2 问题由来 2515.6.3 从库system lock延迟的原因 2515.6.4 system lock问题分析 2525.6.5 模拟测试 253