mysql主机宕机数据库启动异常修复办法

MySQL主机宕机机器up后,启动MySQL报错如下

231103 13:29:04  InnoDB: Assertion failure in thread 140292406581598 in file trx0purge.c line 822
InnoDB: Failing assertion: purge_sys->purge_trx_no <= purge_sys->rseg->last_trx_no
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to https://jira.mariadb.org/
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
231103 13:29:04 [ERROR] mysqld got signal 6 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.

To report this bug, see http://kb.askmonty.org/en/reporting-bugs

We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

mariadb 版本 5.5.68-MariaDB,如上报错说是事务清除功能已达到不可能的状态,并通过断言崩溃以保护数据,innodb不能recovery,导致数据库起不来。

这有两种可能:mysql的bug或者的数据损坏,大概率是innodb恢复文件损坏,只能想办法恢复数据了。

解决办法

方法1. 从备份中恢复数据

方法2. 如果是mysql集群,且集群有多个实例,通过物理拷贝从库数据创建新从库也可以恢复

方法3. 如果没有备份,单实例,可以通过强制模式恢复数据

注意:如果没有设置innodb_flush_log_at_trx_commit=1sync_binlog=1,1,3方法可能会有数据丢失。

恢复数据

方法1 从备份中恢复数据

是通过全量备份和增量备份binlog恢复,这种方法比较大众就不说了。

方法2 速度最快,物理拷贝从库数据恢复

前提条件:是你的mysql集群实例充足,至少是2n+1的实例数且集群减少两个实例不影响业务

操作步骤:

  1. 1. 从负载均衡器上摘除实例A
  2. 2. 停掉实例A的复制线程stop slave
  3. 3. 停掉实例A的mysql进程
  4. 4. 删除待恢复的实例B的数据目录
  5. 5. copy 实例A的数据到待恢复的实例B数据目录里
  6. 6. 启动实例B和刚停掉的实例A,待主从延迟追上后即可把他们挂到负载均衡器上

方法3 通过强制模式恢复数据

针对没有备份且单实例的数据库,可以通过强制模式恢复数据

innodb_force_recovery 配置参数介绍

我们先来看下innodb恢复数据配置参数innodb_force_recovery,它影响整个InnoDB存储引擎的恢复状况。

默认为0,表示当需要恢复时执行所有的恢复操作(即校验数据页/purge undo/insert buffer merge/rolling back&forward),当不能进行有效的恢复操作时,mysql有可能无法启动,并记录错误日志;

innodb_force_recovery可以设置为1-6,大的数字包含前面所有数字的影响。当设置参数值大于0后,可以对表进行select,create,drop操作,但insert,update或者delete这类操作是不允许的。

**1(SRV_FORCE_IGNORE_CORRUPT)**:即使服务器检测到损坏的页仍让它运行。试图使SELECT* FROM tbl_name跳过损坏的索引记录和页,这样有助于转储表。忽略检查到的 corrupt 页。尽管检测到了损坏的 page 仍强制服务运行。一般设置为该值即可,然后 dump 出库表进行重建。

**2(SRV_FORCE_NO_BACKGROUND)**:阻止主线程和任何清除线程的运行。如果崩溃会在清除操作中发生,该恢复值会阻止它。如主线程需要执行 full purge 操作,会导致 crash。阻止 master thread 和任何 purge thread 运行。若 crash 发生在 purge 环节则使用该值。

**3(SRV_FORCE_NO_TRX_UNDO)**:不执行事务回滚操作。

**4(SRV_FORCE_NO_IBUF_MERGE)**:阻止插入缓冲合并操作。如果它们会导致崩溃,不要做这些。不计算表统计。这个值可以永久损坏数据文件。使用这个值后,准备好删除并重建所有辅助索引。在MySQL5.6.15中,设置InnoDB为只读。

**5(SRV_FORCE_NO_UNDO_LOG_SCAN)**:在启动数据库时不查看撤消日志:InnoDB将即使未完成的事务也作为已提交。这个值可以永久损坏数据文件。在MySQL5.6.15中,设置InnoDB为只读。

**6(SRV_FORCE_NO_UNDO_LOG_SCAN)**:不执行前滚的操作。恢复时不做 redo log roll-forward。这个值可能永久损坏数据文件。数据库页被留在一个陈旧的状态,这反过来又可能带给B-trees和其它数据库结构更多的损坏。在MySQL5.6.15中,设置InnoDB为只读。

所以我们知道innodb_force_recovery参数值约小越好,我们在恢复时,先按最小到最大的值一步步尝试看用最小的值是否能启动mysql进程。

配置my.cnf

在mysql配置文件[mysqld]下增加如下

[mysqld]
innodb_purge_threads=0
innodb_force_recovery = N

注意:

  1. 1. innodb_force_recovery = N,先设置N的值为1启动mysql如果不能启动再设置2,以此类推。。
  2. 2. 如果配置innodb_force_recovery值大于0,就要设置innodb_purge_threads=0,否则就会出现InnoDB: Waiting for the background threads to start的错误

启动mysql并备份数据

在启动mysql之前,最好先把数据目录备份一下,假如你的数据目录是/var/lib/mysql

备份数据目录:cp /var/lib/mysql /var/lib/mysql.back ,注意看磁盘空间是否够,不够转存到远端存储

然后启动数据库,备份所有数据

systemctl start mariadb

mysqldump -uroot -p --all-databases > all.sql

恢复数据

注释my.cnf增加的配置

[mysqld]
#innodb_purge_threads=0
#innodb_force_recovery = N

停mysql

systemctl stop mariadb

删除数据目录

rm /var/lib/mysql/* -rf

再次启动mysql

systemctl start mariadb

执行mysql安全脚本,配置root密码

mysql_secure_installation

最后,从备份中恢复数据

mysql -uroot -p < all.sql

同一主机上启动多台MySQL服务器

在同一个物理主机上启动多台MySQL服务器,通常也称为单机多实例。部署单机多实例可以用于测试新版本的功能、测试复制功能、高可用性等目的。用户可以通过启动mysqld或者mydqld_safe并指定不同的配置文件来启动,例如,

mysqld --socket=/mysql/socket1 --port=3306 --datadir=/mysql/data1mysqld --socket=/mysql/socket2 --port=3307 --datadir=/mysql/data2

例如,创建一个配置文件my.cnf1,内容如下:

[mysqld]
socket=/mysql/socket1port=3306datadir=/mysql/data1

通过mysqld_safe启动MySQL实例,

mysqld_safe --defaults-file=/mysql/my.cnf1

用户也可以使用mysqld_multi管理多个相似的服务器。通过mysqld_muiti管理同一主机上的多个MySQL服务器时,每个mysqld进程通过主机的不同socket文件或TCP/IP端口等监听连接,在配置文件中通过[mysqldN]对每个MySQL服务器进行配置,例如,[mysqld1],[mysqld2]。

配置文件的示例如下:

[mysqld1]user=mysqldatadir=/mysql/data1port=3306socket=/mysql/socket1
[mysqld2]user=mysqldatadir=/mysql/data2port=3307socket=/mysql/socket2

启动时使用如下命令,

mysqld_multi --defaults-file=multi.cnf start 1,2

 

此外用户通过systemd服务管理器可以管理多个服务实例。服务管理器通过mysqld@.service配置文件管理多个MySQL服务器实例。配置文件的示例如下:

 

[mysqld@replica01]datadir=/var/lib/mysql-replica01socket=/var/lib/mysql-replicaa01/mysql.sockport=3306log-error=/var/log/mysqld-replica01.log[mysqld@replica02]datadir=/var/lib/mysql-replica02socket=/var/lib/mysql-replicaa02/mysql.sockport=3307log-error=/var/log/mysqld-replica02.log

启动时,使用如下命令:

systemctl start mysqld@replica01

查看全部实例状态时,可以使用如下命令:

systemctl status mysqld@replica*

注意,配置多个实例时需要注意如下选项必须唯一:

  • 数据路径–datadir必须为不同的实例指定不同的位置。
  • 连接层–port、 –socket等选项的值必须唯一。
  • 日志文件和PID文件,默认情况下这类文件保存在数据路径下,如果用户使用其他值则需要为–log-error等日志文件选项和–pid-file指定唯一值。

需要注意,每个TCP/IP端口(IP地址+端口)只能监听一个MySQL实例,如果用户在同一主机上使用相同端口运行两个MySQL实例,需要为其绑定不同的IP地址,例如,两个实例端口同样为3306,其中一个使用bind-address 127.0.0.1,另外一个bind-address 192.168.1.16。

原创文章,作者:速盾高防cdn,如若转载,请注明出处:https://www.sudun.com/ask/76823.html

(0)
速盾高防cdn's avatar速盾高防cdn
上一篇 2024年5月23日 下午4:16
下一篇 2024年5月23日 下午4:22

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注