当错误删除了 MySQL 的 InnoDB 数据库档案 ibdata 及 ib_logfile, 如果 MySQL 服务器仍在执行状态, 而且资料可以照常写入, 切记不要关闭 MySQL 服务器或 kill 掉 mysqld, 这时还可以将 InnoDB 数据库修复的, 以下记录修复的步骤, 如果要测试, 切记在测试环境进行, 切勿在生产环境测试:
1. 先找出 mysqld 的 pid, 可以用 netstat 查询:
|
1 2 |
# netstat -ntlp | grep mysqld tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1921/mysqld |
上面的例子看到, mysqld 的 pid 是 1921.
2. 然后执行以下指令:
|
1 2 3 4 |
# ls -l /proc/1921/fd/ | grep -e ibdata -e ib_ lrwx------ 1 mysql mysql 64 Mar 24 17:30 3 -> /var/lib/mysql/ibdata1 lrwx------ 1 mysql mysql 64 Mar 24 17:30 8 -> /var/lib/mysql/ib_logfile0 lrwx------ 1 mysql mysql 64 Mar 24 17:30 9 -> /var/lib/mysql/ib_logfile1 |
要记下上面返回的结果, 上面例子只有 3 个档案, 记下日期时间后的档案名称, 上面例子是 3, 8 及 9.
3. 以下步骤是登入 MySQL 并执行以下 MySQL 指令, 以下指令的作用是停止 MySQL 写入工作:
|
1 2 |
mysql> FLUSH TABLES WITH READ LOCK; Query OK, 0 rows affected (0.335 sec) |
输入以下指令加快停止的时间:
|
1 2 |
mysql> set global innodb_max_dirty_pages_pct=0; Query OK, 0 rows affected (0.01 sec) |
现在要等待所有 dirty pages 完全写入硬盘, 用 “SHOW ENGINE INNODB STATUS” 查询:
|
1 |
mysql> SHOW ENGINE INNODB STATUS; |
回传的结果很长, 需要查看其中几项, 以确保完全没有写入动作, 先看 “LOG” 段落 的 “Checkpoint age”, 当看到 “Checkpoint age” 是 “0” 才完成。
|
1 2 3 4 5 6 7 8 9 10 |
--- LOG --- Log sequence number 1597945 Log flushed up to 1597945 Last checkpoint at 1597945 Max checkpoint age 7782360 Checkpoint age target 7539162 Modified age 0 Checkpoint age 0 |
然后查看 “INSERT BUFFER AND ADAPTIVE HASH INDEX” 段落的 “Ibuf”, 数值需要等于 1:
|
1 2 3 4 |
------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf: size 1, free list len 0, seg size 2, 0 merges |
另一个要检查的项目是 TRANSACTIONS 段落, 确保 Purge 进程把 undo log 全部清除掉, 交易 ID 要一样:
|
1 2 3 4 5 |
------------ TRANSACTIONS ------------ Trx id counter 500 Purge done for trx's n:o < 0 undo n:o < 0 |
确保 MySQL 完全没有写入工作后, 可以进行下一步, 复制 InnoDB 的档案回数据库目录。
4. 把第 2 步看到的档案复制到原来的 MySQL 目录:
# cp 3 /var/lib/mysql/ibdata1
# cp 8 /var/lib/mysql/ib_logfile0
# cp 9 /var/lib/mysql/ib_logfile1
5. 修改档案 owner 为 mysql:
6. 最后重新启动 MySQL 服务器: