三角洲辅助卡盟新版上线,应有尽有
当前位置:首页 > 游戏攻略> 正文

第4章大难临头

发布时间:06/21 10:27:49
生产数据库崩溃急救:从死锁到数据恢复的实战指南

第一步:确认故障现场与紧急止损

当数据库崩溃或无法连接时,首要任务是防止错误扩散,严禁直接重启数据库服务或服务器,这可能导致数据文件损坏无法恢复。必须先切断业务端写入,保护现场。

1. 检查MySQL服务状态

执行以下命令确认服务是否还存活,以及当前的PID或错误信息:

```bash systemctl status mysqld ```

如果服务处于 faileddead 状态,继续执行以下步骤查看详细报错。

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