一、前言
【被记大过了,一个操作把MySQL主从复制整崩了……】最近公司某项目上反馈MySQL主从复制失败,被运维部门记了一次大过,影响到了项目的验收推进,那么究竟是什么原因导致的呢?而主从复制的原理又是什么呢?本文就对排查分析的过程做一个记录 。
二、主从复制原理
我们先来简单了解下MySQL主从复制的原理 。
文章插图
1.主库master 服务器会将 SQL 记录通过 dump 线程写入到二进制日志binary log中 。
2.从库slave 服务器开启一个 io thread 线程向服务器发送请求,向 主库master 请求 binary log 。主库master 服务器在接收到请求之后,根据偏移量将新的 binary log 发送给 slave 服务器 。
3.从库slave 服务器收到新的 binary log 之后,写入到自身的 relay log 中,这就是所谓的中继日志 。
4.从库slave 服务器,单独开启一个 sql thread 读取 relay log 之后,写入到自身数据中,从而保证主从的数据一致 。
以上是MySQL主从复制的简要原理,更多细节不展开讨论了,根据运维反馈,主从复制失败主要在IO线程获取二进制日志binlog超时,一看主数据库的binlog日志竟达到了4个G,正常情况下根据配置应该是不超过300M 。
文章插图
三、binlog写入机制
想要了解binlog为什么达到4个G,我们来看下binlog的写入机制 。
binlog的写入时机也非常简单,事务执行过程中,先把日志写到 binlog cache ,事务提交的时候,再把binlog cache写到binlog文件中 。因为一个事务的binlog不能被拆开,无论这个事务多大,也要确保一次性写入,所以系统会给每个线程分配一个块内存作为binlog cache 。
文章插图
- 上图的write,是指把日志写入到文件系统的page cache,并没有把数据持久化到磁盘,所以速度比较快
- 上图的fsync,才是将数据持久化到磁盘的操作, 生成binlog日志中
所以说怀疑是不是遇到了大事务,因而我们需要看看binlog中的内容具体是哪个事务导致的 。
四、查看binlog日志
我们可以使用mysqlbinlog这个工具来查看下binlog中的内容,具体用法参考官网:https://dev.mysql.com/doc/refman/8.0/en/mysqlbinlog.html 。
1.查看binlog日志
./mysqlbinlog --no-defaults ---output=decode-rows -vv /mysqldata/mysql/binlog/mysql-bin.004816|more
2.以事务为单位统计binlog日志文件中占用的字节大小
./mysqlbinlog --no-defaults ---output=decode-rows -vv /mysqldata/mysql/binlog/mysql-bin.004816|grep GTID -B1|grep '^# at' | awk '{print $3}' | awk 'NR==1 {tmp=$1} NR>1 {print ($1-tmp, tmp, $1); tmp=$1}'|sort -n -r|more
文章插图
生产中某个事务竟然占用4个G 。
3.通过start-position和stop-position统计这个事务各个SQL占用字节大小
./mysqlbinlog --no-defaults ---output=decode-rows --start-position='xxxx' --stop-position='xxxxx' -vv /mysqldata/mysql/binlog/mysql-bin.004816 |grep '^# at'| awk '{print $3}' | awk 'NR==1 {tmp=$1} NR>1 {print ($1-tmp, tmp, $1); tmp=$1}'|sort -n -r|more
文章插图
发现最大的一个SQL竟然占用了32M的大小,那超过10M的大概有多少个呢?
4.通过超过10M大小的数量
./mysqlbinlog --no-defaults ---output=decode-rows --start-position='xxxx' --stop-position='xxxxx' -vv /mysqldata/mysql/binlog/mysql-bin.004816|grep '^# at' | awk '{print $3}' | awk 'NR==1 {tmp=$1} NR>1 {print ($1-tmp, tmp, $1); tmp=$1}'|awk '$1>10000000 {print $0}'|wc -l
文章插图
统计结果显示竟然有200多个,毛估一下,也有近4个G了.
5.根据pos, 我们看下究竟是什么SQL导致的
./mysqlbinlog --no-defaults ---output=decode-rows --start-position='xxxx' --stop-position='xxxxx' -vv /mysqldata/mysql/binlog/mysql-bin.004816|grep '^# atxxxx' -C5| grep -v '###' | more
推荐阅读
- 给AI打下手,我被抢了“饭碗”
- 几个被淘汰的Python库,请不要再用!
- 被同事看不起,多半是习惯了做好人,纠正这三点就可以了
- 广东"十大美食",你全吃过了吗?来看看你少吃了哪些。
- “放浪形骸”余诗曼:传与袁咏仪抢张智霖,被郑嘉颖踢下车
- 孙怡深夜被骂上了热搜!
- 张紫妍被潜后自尽,被曝曾接待4个财阀被玩到不能走路
- 医学生笔试第1名,因身高1米3频频被刷,网友却说医院做得对
- 港媒曝郑欣宜失联俩月后续:遭男友非人对待、房被抢、与公司闹掰
- 陈建州被曝曾骚扰S妈,与具俊晔一样的怪癖,汪小菲与二人区别明显