当前位置: 首页 > 科技观察

误操作MySQL引发的事故,“高可用”受不了!

时间:2023-03-21 00:26:06 科技观察

我们项目上次不是部署了MySQL高可用吗?MySQL双主模式+Keepalived保证高可用。简单的说就是有两个MySQL主节点,在主机上安装两个Keepaliveds来监控MySQL的状态。一旦发现问题,MySQL就会重启,客户端会自动连接到另一个MySQL。具体可以参考悟空写的这篇文章:实战MySQL高可用架构这次是我们在项目中遇到的意外,一起来回顾一下吧。本文内容如下:事故现场环境:测试环境时间:上午10:30反馈人员:测试组,油炸锅,经研发同事初步排查,可能是数据库问题。然后开始寻找原因。因为这个集群环境是我自己部署的,所以过来查看的时候比较熟悉。系统部署图先说一下系统的部署图,方便大家理解。两个数据库分别部署在node55和node56节点上,相互之间是主从关系,所以称为双主。在node55和node56上也部署了两个Keepaliveds,分别监控MySQL容器的状态。报错原因及解决方法①我的第一个想法是,不是有Keepalived来保证高可用吗?即使MySQL挂了,也可以通过Keepalived自动重启。就算一个不能重启,有没有另一个可以用的?②然后去服务器上查看MySQL容器的状态。到两台MySQL服务器上,首先查看MySQL容器的状态,运行dockerps命令,发现这两个MySQL容器不在列表中,说明容器没有正常运行。③这个不行,不过我安装了Keepalived高可用组件。难道Keepalived也挂了?④快速查看一波Keepalived,发现两个Keepalived运行正常。通过执行命令查看:systemctlstatuskeepalived⑤Nani,Keepalived也正常。Keepalived将每隔几秒重新启动MySQL。也许在那短暂的空闲时间内我没有看到MySQL容器启动?执行另一个命令dockerps-a,列出所有容器的状态。可以看到MySQL启动后就退出了,说明MySQL确实在重启。⑥也就是说,虽然Keepalived重启了MySQL容器,但是MySQL本身有问题,那么Keepalived的高可用也无济于事。⑦如何解决?你只能看到MySQL报告了什么错误。执行命令查看容器日志。docker记录。查找最近的日志:⑧提示mysql-bin.index文件不存在,这个文件是在主从同步中配置的,在my.cnf配置中。完成此配置后,在进行主从同步时,会在var/lib/mysql/log目录下生成多个mysql-bin.xxx文件。还有一个mysql-bin.indexindex文件,它会标记现在记录binlog日志文件的位置。mysql-bin.index文件内容如下:/var/lib/mysql/log/mysql-bin.000001这个mysql-bin.000001文件还是有序号的,这里还有坑,我再说稍后再说。⑨报错是缺少mysql-bin.index,查看一下,没有!不管这个文件是怎么消失的,先建立这个log文件夹,然后mysql会自动帮我们生成这个文件。解决方法:执行以下命令创建文件夹并添加权限。mkdirlogchmod777log-R⑩日志目录在两台服务器上都存在后,Keepalived也自动帮我们重启了MySQL容器,然后访问了其中一个节点node56的MySQL状态。哎,报错了。Last_IO_Error:Gotfatalerror1236frommasterwhenreadingdatafrombinarylog:'Couldnotfindfirstlogfilenameinbinarylogindexfile'可以看到几个关键信息:Slave_IO_Running:NO,当前同步I/O线程没有运行,这个I/O线程是从库的,它会请求主库的binlog,并将获取到的binlog写入本地的relay-log(中继日志)文件。如果没有运行,说明从库同步没有正常运行。Master_Log_File:mysql-bin.000014,表示当前同步日志文件为000014,我们看到节点node56上的mysql.index中包含000001,这个000014根本不在索引文件中,所以会报错被举报了这就涉及到主从同步的原理。上图:从库会生成两个线程,一个I/O线程,一个SQL线程;I/O线程会请求主库的binlog日志文件,并将获取到的binlog日志文件写入本地relay-log(中继日志)文件;主库会生成dump线程将binlog传递给从库I/O线程;SQL线程会读取中继日志文件中的日志,并将其解析成SQL语句,一条一条执行。那很容易,我们可以重新指定同步哪个日志文件,同步到哪里。解决方法:查看主库node55上的日志文件状态。记下这两条信息:File=mysql-bin.00001,Position=117748。(这里还有一个坑:先锁表,再看这两个值,从库同步后再解锁表)。具体执行命令如下:FLUSHTABLESWITHREADLOCK;SHOWMASTERSTATUSUNLOCKTABLES然后在从库node56上重新指定同步的日志文件和位置:#停止从库同步STOPSLAVE;#设置同步文件和位置CHANGEMASTERTOMASTER_HOST='10.2.1.55',MASTER_PORT=3306,MASTER_USER='vagrant',MASTER_PASSWORD='vagrant',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=117748;#开启同步STARTSLAVE;再次检查没有报错,我的/O线程也在运行,这里插入图片描述然后使用node55作为从库,node56作为主库,同样执行以上步骤,状态显示正常,然后用navicat工具连接数据库,一切正常,经过测试组反馈的结果,大功告成。我好像忘记了一个问题,为什么log文件夹被删除了??为什么有问题?然后我问有没有人当时把/var/lib/mysql/log这个目录删了,没有人会随便删这个目录。但是我发现log/var/lib/mysql的父目录下还有很多其他的文件夹,比如xxcloud,xxcenter等等。这不就是我们项目中的几个数据库的名字吗?这个目录下的文件夹只要在navicat上显示,都是一一对应的,如下图。它还显示日志数据库。有人会从navicat杀掉日志数据库吗?很可能!果不其然,有同事在迁移升级的过程中,发现旧系统中不存在日志数据库,于是清理了一下。这相当于同时杀死日志数据库和日志文件夹。嗯,终于真相大白了!这其实是我前期没有考虑日志目录的问题。没错,这是我的错~改进其实在操作和同步数据库的时候,不应该使用这种overlay同步的方式。可以使用单库同步的方式,日志库不会被kill掉。不过有点奇怪,这个日志数据库放在这里,难道不能出现在这里吗?我们只需要指定日志目录不在/var/lib/mysql目录下即可。东哥建议:将日志文件和数据库数据文件分开:datadir=/var/lib/mysql/datalog_bin=/var/lib/mysql/log另外一个问题,我们的高可用真的是高可用吗?至少我没有及时报警,不知道MySQL数据库宕机了。都是同学通过测试反馈的。能及时感知MySQL异常吗?这里可以使用Keepalived的功能来发送邮件,或者使用日志报警系统。这是后期需要改进的地方。

最新推荐
猜你喜欢