这篇文章有点奇怪(而且很长,抱歉),我正在与一位在 Windows(Server 2008 R2)上运行 MariaDB 的客户合作。他们有几个大型 MyISAM 表(每个表高达 30 GB,2 亿多行),出于多种原因,我将它们转换为 InnoDB。大多数表转换得很好,但其中少数表完全锁定了 InnoDB 引擎。当我说完全锁定时,我的意思是进度百分比停止增加,mysqld 的所有 CPU/磁盘活动都停止,并且大多数与 InnoDB 相关的任务都停止工作。甚至运行“SHOW ENGINE InnoDB STATUS”也会挂起。我让它静置了一天,它仍然保持在相同的百分比。
需要注意以下几点:
- 它在 ESXi VM 中运行并且是其生产 VM 的克隆,因此绝对没有流量(单独的硬件,没有客户端连接)。
- 该虚拟机有 8 个 CPU 核心和 16 GB RAM,两者都没有受到任何压力。
- 我尝试禁用查询缓存,结果没有变化
- 如前所述,转换过程将在第 1 阶段(复制到 tmp 表)的中间某处挂起,百分比将停止增加。此时,mysqld 不再有 CPU 或磁盘活动。
- 挂起时没有任何记录,只有之前有关长信号量等待的消息。
- 我们正在运行 innodb_file_per_table。
- 凭直觉,我确认临时的 .ibd 文件没有变得太碎片化,在上次转换尝试中它有 99 个碎片。
- 并非所有表都发生这种情况,也并非只发生在最大的表上。我有一个 7 GB 的表(有 100m 行)失败,而一个 30 GB 的表(有 200m 行)成功。
- 它总是在桌子上的同一个地方失败。
- 所有表都已完成完整的 MyISAM 检查/修复
- Windows 系统日志中未记录任何错误
- 我们正在运行最新的 10.2 分支(稳定版)。我考虑升级到 10.3,但我在发行说明中没有看到任何与之相关的内容。
- 检查 procexp,mysqld 中有两个活动线程,均显示 ntoskrnl.exe!KeWaitForMultipleObjects+0xc0a。两个堆栈的屏幕截图如下。
- 检查 procmon,mysqld.exe 中绝对没有任何活动。
- 当它挂起时,可以查询 MyISAM 表,但任何 InnoDB 查询都会挂起。
- 我确实找到了此主题并设置 innodb_adaptive_hash_index=0 但没有任何区别。
- 系统的其他方面都运行良好(尽管它只是一个 SQL 服务器),并且已经重新启动过几次。
- 有些人可能注意到我已经关闭了 doublewrite,这仅用于测试并且将在生产中被禁用。
日志中可能重要的数据摘录:(重复多次)
InnoDB:######启动 InnoDB Monitor 30 秒以打印诊断信息: InnoDB:待处理读取 0,写入 0 ===================================== 2017-12-28 15:54:44 0x3c8 INNODB 监视器输出 ===================================== 从过去 17 秒计算出的每秒平均值 ----------------- 背景线程 ----------------- srv_master_thread 循环:1788 srv_active、0 srv_shutdown、67 srv_idle srv_master_thread 日志刷新并写入:1854 ---------- 信号量 ---------- OS WAIT ARRAY INFO:预留计数 59085 --线程 3892 已在 ibuf0ibuf.cc 行 3460 等待信号量 247.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 00000000975EFC68 处的 RW 闩锁上创建了 S 锁 一个编写器(线程 ID 3800)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定在文件 ibuf0ibuf.cc 第 3460 行 上次写入锁定在文件 mtr0mtr.ic 第 147 行 --线程 2944 已在 ibuf0ibuf.cc 行 4578 等待信号量 247.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 00000000975EFC68 处的 RW 闩锁上创建了 S 锁 一个编写器(线程 ID 3800)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定在文件 ibuf0ibuf.cc 第 3460 行 上次写入锁定在文件 mtr0mtr.ic 第 147 行 --线程 3700 已在 buf0flu.cc 行 1246 等待信号量 246.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 00000000975EFC68 处的 RW 闩锁上创建了 SX 锁 一个编写器(线程 ID 3800)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定在文件 ibuf0ibuf.cc 第 3460 行 上次写入锁定在文件 mtr0mtr.ic 第 147 行 --线程 3800 已在 buf0buf.cc 行 4136 等待信号量 247.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 000000018299B078 处的 RW 闩锁上创建了 S 锁 一个写入器(线程 ID 0)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定文件尚未保留第 0 行 上次写入锁定在文件 buf0buf.cc 第 5363 行 --线程 2564 已在 ibuf0ibuf.cc 行 4578 等待信号量 247.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 00000000975EFC68 处的 RW 闩锁上创建了 S 锁 一个编写器(线程 ID 3800)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定在文件 ibuf0ibuf.cc 第 3460 行 上次写入锁定在文件 mtr0mtr.ic 第 147 行 --线程 3484 已在 ibuf0ibuf.cc 行 4578 等待信号量 247.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 00000000975EFC68 处的 RW 闩锁上创建了 S 锁 一个编写器(线程 ID 3800)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定在文件 ibuf0ibuf.cc 第 3460 行 上次写入锁定在文件 mtr0mtr.ic 第 147 行 --线程 3200 已在 ibuf0ibuf.cc 行 2720 等待信号量 246.00 秒: 互斥锁位于 00000001406064F8,互斥锁 IBUF 创建 ibuf0ibuf.cc:516,锁定变量 2 OS 等待数组信息:信号计数 46563 RW 共享旋转 0,轮数 53529,操作系统等待 24403 RW-excl 旋转 0,轮次 480664,OS 等待 7825 RW-sx 旋转 2641 次,循环 24044 次,操作系统等待 184 次 每次等待的旋转轮数:53529.00 RW-共享,480664.00 RW-排除,9.10 RW-sx ------------ 交易 ------------ Trx ID 计数器 94794 清除 trx 的 n:o < 94152 已完成,撤消 n:o < 0 状态:正在运行但空闲 历史列表长度 0 每次交易的清单: ---TRANSACTION 281476765058824,未开始 0 个锁结构、堆大小 1136、0 个行锁 ---交易 94793,活动 247 秒插入 mysql 表正在使用 1,锁定 1 1 个锁结构、堆大小 1136、0 个行锁、撤消日志条目 1930 MySQL 线程 ID 8、OS 线程句柄 3892、查询 ID 1 ::1 根复制到 tmp 表 改变表 dbname.table_being_converted 引擎=innodb -------- 文件输入/输出 -------- I/O 线程 0 状态:完成 buf 页的 io(插入缓冲区线程) I/O 线程 1 状态:完成 buf 页的 io(日志线程) I/O 线程 2 状态:完成 buf 页的 io(读线程) I/O 线程 3 状态:完成 buf 页的 io(读线程) I/O 线程 4 状态:本机 aio 句柄(读取线程) I/O 线程 5 状态:本机 aio 句柄(读取线程) I/O 线程 6 状态:本机 aio 句柄(写线程) I/O 线程 7 状态:本机 aio 句柄(写线程) I/O 线程 8 状态:本机 aio 句柄(写线程) I/O 线程 9 状态:本机 aio 句柄(写线程) 待处理的正常 aio 读取:[0, 0, 2, 4] ,aio 写入:[0, 0, 0, 0], ibuf aio 读取:,记录 i/o:,同步 i/o: 待处理刷新 (fsync) 日志:0;缓冲池:0 108072 次 OS 文件读取、2437337 次 OS 文件写入、23912 次 OS fsync 0.00 读取/秒、0 平均字节/读取、0.00 写入/秒、0.00 fsyncs/秒 ------------------------------------- 插入缓冲区和自适应哈希索引 ------------------------------------- InnoDB:###### 诊断信息打印到标准错误流 2017-12-28 15:55:09 3240 [警告] InnoDB:长时间信号量等待: --线程 3892 已在 ibuf0ibuf.cc 行 3460 等待信号量 272.00 秒: 在文件 buf0buf.cc 第 1471 行中,在 00000000975EFC68 处的 RW 闩锁上创建了 S 锁 一个编写器(线程 ID 3800)已将其保留为独占模式 读者数量 0,等待者标志 1,lock_word:0 上次读取锁定在文件 ibuf0ibuf.cc 第 3460 行 上次写入锁定在文件 mtr0mtr.ic 第 147 行 (剪辑,上面的数据重复了很多次)
my.ini 内容:
[mysqld] datadir=D:/SQLData 端口=3306 默认存储引擎=InnoDB innodb_buffer_pool_size=4096M innodb_log_file_size=256M innodb_doublewrite = 0 表 1. innodb_file_per_table innodb_force_recovery=1 最大连接数=500 查询缓存大小=4096M 跳过名称解析 慢查询日志 日志错误=Errors.log myisam_sort_buffer_size=768M 临时表大小=768M 密钥缓冲区大小=2048M 读取缓冲区大小=5M 排序缓冲区大小=32M