第4章大难临头
第一步:确认故障现场与紧急止损
当数据库崩溃或无法连接时,首要任务是防止错误扩散,严禁直接重启数据库服务或服务器,这可能导致数据文件损坏无法恢复。必须先切断业务端写入,保护现场。
1. 检查MySQL服务状态
执行以下命令确认服务是否还存活,以及当前的PID或错误信息:
```bash systemctl status mysqld ```如果服务处于 failed 或 dead 状态,继续执行以下步骤查看详细报错。
2. 定位核心错误日志
不要猜测原因,直接读取日志文件最后50行。默认路径通常为 /var/log/mysqld.log:
```bash tail -n 50 /var/log/mysqld.log ```关键报错识别:
- InnoDB: Assertion failure:内存数据一致性校验失败,通常需要强制恢复。
- InnoDB: Log block number x is out of range:Redo log日志损坏,需重建日志。
- InnoDB: Database page corruption:数据页物理损坏,需通过备份或跳过损坏页恢复。
3. 立即冻结应用层写入
在数据库未修复前,必须停止所有应用服务(如Nginx、Tomcat、Java Jar包),防止持续写入导致脏页堆积或从库同步延迟过大:
```bash 示例:停止Nginx systemctl stop nginx 示例:停止Java应用 ps -ef | grep java | grep -v grep | awk '{print $2}' | xargs kill -9 ```第二步:配置InnoDB强制恢复模式
针对常见的"大难临头"场景(如断电导致文件损坏),MySQL提供了 innodb_force_recovery 参数。该参数允许InnoDB引擎在启动时跳过损坏检查部分,从而将服务拉起以导出数据。
1. 修改配置文件
打开 /etc/my.cnf 文件,在 [mysqld] 模块下添加或修改以下参数:
```ini [mysqld] 建议从1开始尝试,最大值为6。级别越高,跳过的检查越多,数据丢失风险越大。 1 (SRV_FORCE_IGNORE_CORRUPT): 忽略检测到的损坏页 2 (SRV_FORCE_NO_BACKGROUND): 阻止主线程运行,防止崩溃 4 (SRV_FORCE_NO_TRX_UNDO): 不执行事务回滚 innodb_force_recovery = 1 ```注意:如果设置为1或2仍无法启动,可依次尝试3、4,但严禁直接设置为6(这会导致数据文件永久性不一致)。
2. 尝试启动数据库
保存配置后,执行启动命令:
```bash systemctl start mysqld ```检查状态,如果显示 active (running),说明强制恢复成功,此时数据库处于"只读"或"受限读写"状态,这是抢救数据的唯一窗口期。
第三步:全量数据导出(核心抢救步骤)
服务启动后,绝对不要进行任何业务操作,立即使用 mysqldump 将所有数据导出为SQL文件。这是重建数据库的基础。
1. 准备存储目录
确保磁盘空间充足,创建备份目录:
```bash mkdir -p /data/backup/emergency ```2. 执行全量导出
使用以下命令导出数据。必须添加 --single-transaction 和 --quick 参数以减少锁表和内存压力:
```bash mysqldump -u root -p \ --single-transaction \ --quick \ --flush-logs \ --master-data=2 \ --all-databases \ --routines \ --triggers \ --events \ > /data/backup/emergency/rescue_$(date +%Y%m%d_%H%M%S).sql ```参数详解:
- --single-transaction:InnoDB表在导出时不锁表,保证一致性。
- --quick:不缓冲查询,直接导出到磁盘,防止大表导致内存溢出。
- --all-databases:导出所有库,不要遗漏。
观察文件生成的大小,直到出现 "Dump completed" 提示。
第四步:重建数据库实例
数据导出完成后,原数据库实例已不可靠。我们需要关闭它,删除损坏的数据文件,利用导出的SQL文件重建一个干净的实例。
1. 停止服务并清理旧数据
```bash systemctl stop mysqld ```找到数据目录(通常在 /var/lib/mysql),重命名 该目录作为备份,不要直接删除,以防二次灾难:
```bash mv /var/lib/mysql /var/lib/mysql_broken_$(date +%Y%m%d) mkdir /var/lib/mysql chown -R mysql:mysql /var/lib/mysql ```2. 重置配置文件
编辑 /etc/my.cnf,删除 或 注释掉 之前添加的 innodb_force_recovery 行。新实例必须在正常模式下运行。
3. 初始化新数据库
执行MySQL初始化命令,生成系统表:
```bash mysqld --initialize --user=mysql ```执行后,注意查看日志输出中的临时root密码(通常在日志末尾):
```bash grep 'temporary password' /var/log/mysqld.log ```4. 启动新实例并修改密码
```bash systemctl start mysqld ```登录数据库(使用上一步获取的临时密码),并立即修改为新密码:
```bash mysql -u root -p 在MySQL命令行中执行: ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewStrongPassword!'; flush privileges; exit; ```第五步:数据导入与业务验证
这是最后一步,将抢救出的数据还原到新实例中。
1. 导入数据
使用 mysql 客户端执行导入:
```bash mysql -u root -p'YourNewStrongPassword!' < /data/backup/emergency/rescue_xxx.sql ```根据数据量大小,这可能需要几分钟到几小时。期间不要中断进程。
2. 核心数据校验
导入完成后,不要立即开放公网流量。先进行核心表的数据量级校验:
```bash mysql -u root -p'YourNewStrongPassword!' -e " SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys') ORDER BY TABLE_ROWS DESC; " ```对比该结果与业务预期的行数是否一致。特别关注核心交易表、用户表。
3. 检查表完整性
执行表检查命令,确保没有遗留的损坏标记:
```sql -- 在MySQL命令行中执行 CHECK TABLE your_core_database.your_core_table QUICK; ```第六步:恢复业务与后续收尾
确认数据无误后,重启应用服务:
```bash systemctl start nginx 启动Java应用或其他中间件 ```观察应用日志,确认数据库连接池正常,无SQL报错。
最后收尾工作:
- 将 /var/lib/mysql_broken_xxx 目录压缩归档,上传到对象存储(如S3/OSS)作为冷备份,保留至少30天后再删除。
- 检查服务器硬件(磁盘SMART信息、内存),确认崩溃是否由硬件故障引起,防止再次"大难临头"。
版权保护: 本文由 741卡盟 原创,转载请保留链接: http://741ka.com/gamenews/18874.html
- 上一篇:暗黑3牧牛杖怎么使用
- 下一篇:2024英雄联盟t0英雄排行
