mysql 数据库是社会普遍认可的非常流行的数据库中间件之一,一套业务系统,数据库的维护也是至关重要的。
应某位网友的要求,我将MySQL 5.7出现故障的恢复的过程记录一下。
问题出现:
2020-05-19T11:48:11.883641Z 0 [ERROR] InnoDB: SYS_FIELDS.INDEX_ID mismatch
11:48:11 UTC - mysqld got signal 11 ;
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.
Attempting to collect some information that could help diagnose the problem.
As this is a crash and something is definitely wrong, the information
collection process might fail.
key_buffer_size=8388608
read_buffer_size=131072
max_used_connections=0
max_threads=151
thread_count=0
connection_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 68195 K bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
Thread pointer: 0x32e60d0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 7ffd56a46910 thread_stack 0x40000
/usr/sbin/mysqld(my_print_stacktrace+0x3b)[0xf0702b]
/usr/sbin/mysqld(handle_fatal_signal+0x461)[0x7b93a1]
/lib64/libpthread.so.0(+0xf5f0)[0x7fdcb11535f0]
/lib64/libc.so.6(+0x13ed5a)[0x7fdcafc44d5a]
/usr/sbin/mysqld(_Z30dict_index_add_to_cache_w_vcolP12dict_table_tP12dict_index_tPK16dict_add_v_col_tmm+0x154)[0x1169014]
/usr/sbin/mysqld[0x117708b]
/usr/sbin/mysqld[0x117ae80]
/usr/sbin/mysqld(_Z15dict_load_tablePKcb17dict_err_ignore_t+0x568)[0x1172a28]
/usr/sbin/mysqld(_Z23dict_table_open_on_namePKcmm17dict_err_ignore_t+0x138)[0x1164598]
/usr/sbin/mysqld(_ZN11ha_innobase15open_dict_tableEPKcS1_b17dict_err_ignore_t+0x39)[0xf3ab39]
/usr/sbin/mysqld(_ZN11ha_innobase4openEPKcij+0x9ff)[0xf505ef]
/usr/sbin/mysqld(_ZN7handler7ha_openEP5TABLEPKcii+0x33)[0x8075f3]
/usr/sbin/mysqld(_Z21open_table_from_shareP3THDP11TABLE_SHAREPKcjjjP5TABLEb+0x8c7)[0xd6cac7]
/usr/sbin/mysqld(_Z10open_tableP3THDP10TABLE_LISTP18Open_table_context+0xe8b)[0xc7714b]
/usr/sbin/mysqld(_Z11open_tablesP3THDPP10TABLE_LISTPjjP19Prelocking_strategy+0x612)[0xc7e102]
/usr/sbin/mysqld(_Z33open_trans_system_tables_for_readP3THDP10TABLE_LIST+0x50)[0xc7edf0]
/usr/sbin/mysqld(_Z10my_tz_initP3THDPKcc+0x6a8)[0xd811c8]
/usr/sbin/mysqld(_Z11mysqld_mainiPPc+0x1b26)[0x7b47e6]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fdcafb28505]
/usr/sbin/mysqld[0x7a91d4]
Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (0): Connection ID (thread ID): 0
Status: NOT_KILLED
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
以上是部分报错日志信息
根据日志信息可以看出是系统表损坏了,而且还给出了参考手册页的地址:http://dev.mysql.com/doc/mysql/en/crashing.html
然后根据参考手册页看了半天,也没找到具体如何解决和修复,于是继续排查问题。
经过查询和了解,发现mysql版本是5.7.24,操作系统是centos 7,截止目前mysql5.7最新版已经是5.7.30,于是升级了mysql相关的软件包,将原来的配置文件进行了备份,安装方式是使用yum在线安装的,所有的配置都是默认,这里由于是生产环境在使用的,不能直接将MySQL所有的删除重新安装,所以只能寻找恢复修复的办法,如果是测试环境,数据不重要的,我这里给出的解决办法是直接将mysql的软件包全部卸载,删除配置文件,数据文件等相关文件,直接重新安装,这种方式是最简单最快捷的。
既然是数据库的系统表损坏了,那么我们顺着这个思路,能不能我们把系统数据库的表给复制一份呢,于是说干就干,就从其他地方复制了一份mysql数据库的系统表到数据库目录下,结果发现仍然不能正常使用,mysqld服务根本就起不来。
到这里就感觉很头大了,网上也搜不到资料,而且各个类型的报错信息都有所不同,别人使用的方式方法,经过验证不适用,无法解决遇到的的问题。
那么,既然多次尝试,在原有的数据库基础上修复不了,那么我们就自己重新安装一个全新的数据库,然后将原来的业务数据库数据拷贝到新的数据库里面。跟着这个思路,我们还是使用yum来安装mysql 5.7.30,安装完成后,由于是默认的配置,而在默认的位置已经有了原有的数据,数据库并没有执行初始化,可以查看到日志显示初始化失败,这里我就不截图了。
于是修改数据库配置文件/etc/my.cnf,这里安装之前一定要把原有的数据库配置文件和数据目录进行备份,以免误操作,造成原有的数据丢失,数据恢复是个比较费时费力的事情,切记,切记!!!
主要修改的内容有:
数据保存目录 :datadir=/opt/mysql
错误日志文件:log-error=/opt/log/mysqld.log
套接字文件:socket=/opt/mysql/mysql.sock
进程文件:pidfile=/opt/mysqld.pid
然后创建相关文件目录:
mkdir -p /opt/mysql
mkdir -p /opt/log
touch /opt/log/mysqld.log
touch /opt/mysql/mysql.sock
touch /opt/mysqld.pid
接着,给文件目录授权,如果文件目录权限不对,同样会造成mysql服务起不来:
chown -R mysql.mysql /opt/mysql
chown -R mysql.mysql /opt/log
chown mysql.mysql /opt/mysqld.pid
chmod -R 755 /opt/mysql
chmod -R 755 /opt/log
######################################################################
启动服务:systemctl start mysqld 没有报错就应该能启动起来
查看状态:systemctl status mysqld 正常的是绿色 显示running
查看密码:grep 'password' /opt/log/mysqld.log
登陆mysql:
mysql -uroot -p
发现使用刚才从日志里面的查看的密码并不能使用,报了一个错误,找不到套接字/var/lib/mysql/mysql.sock
这是因为mysql客户端默认使用的套接字是/var/lib/mysql/mysql.sock
于是我们在登陆的时候加上参数 -S /opt/mysql/mysql.sock 来指定我们自定义的套接字文件
或者我们建立软链接,将我们自定义的套接字文件指向默认位置,
rm -rf /var/lib/mysql/mysql.sock
ln -s /opt/mysql/mysql.sock /var/lib/mysql/mysql.sock
然后再用日志里面查看的初始密码来登陆就可以成功!!! 这里是需要注意的地方。
(其实也可以在配置文件中无需修改套接字文件位置,保持默认)
登陆成功后,就可以修改密码:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass123_';
这里因为默认是开启了密码验证,所以要设置了符合验证规则的密码
validate_password=off 配置文件中加入这句即可关闭密码验证
修改密码后,配置允许使用root远程连接:
grant all privileges on *.* to 'root'@'%' identified by 'MyNewPass123_' with grant option;
flush privileges;
接下来,将业务系统的数据目录直接拷贝到新的数据目录下:
cp -a -r /var/lib/mysql/xxx /opt/mysql/
登陆数据库,查看数据库和表:
mysql -uroot -p
show databases;
use xxx;
show tables;
最后验证效果,发现有部分数据丢失,但是大部分数据都没影响,可以正常使用。
以上内容,仅做个人记录,仅供参考使用,如有错漏之处,欢迎大家批评指正!!!
总结:
数据库是业务系统中非常重要的东西,一旦发生故障将影响业务系统的正常运行,造成损失,建议使用多台数据库做集群,并定期做备份,这样可以避免单节点故障和数据库宕机等引起的数据丢失。