开发问MySQL 大事务证据,一个脚本堵上他的嘴

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, OceanBase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共2400人左右 1 + 2 + 3 + 4 +5 + 6 + 7)(1 2 3 4 5 群均已爆满,6群接近400人即将关闭自由申请,开7群)

16097baf6b63a3d07d592b6044f53128.png

MySQL的Binlog是一个经常被提起,且认为功能丰富的日志,实际上BINLOG 负担的任务,有两个第一为数据复制到其他节点,起到了数据传递的功能,第二是数据的操作记录包含了DDL和DML操作等,帮助在数据库出现问题的时候,进行数据的恢复等,很多MYSQL误操作后的恢复就是从Binlog中进行的,同时Binlog在MySQL运行中并不是必须的,

今天咱们咱们就说说Binlog的一些问题和通过一个简单的awk来进行日志的分析的脚本。

问题1:Binlog 选择mix格式,会导致主从的数据不一致吗?

会的,mix是Binlog 采用SBR,RBR混合的方式,在一些情况下选择使用了SBR,statement的方式会导致传递到从库的数据与主库不一致。比如,uuid函数,Now()函数,Rand()等函数,在UPDATE ,INSERT 等语句中使用,这些非确定行的函数如果数据库选择了传递的方式为sbr,那么就有可能导致你的主从数据不一致。

同时如果有自定义函数等,在使用中更是有可能导致数据的主从不一,所以在MySQL的使用中要严格使用 RBR的模式,也就是MySQL官方一直提及的 row模式。

问题2 :MySQL的并行复制是否会导致业务逻辑错误?

会的, MySQL在后期尤其8.0后最重要的改变之一就是组提交,的并行复制,按照原理在尽显并行的数据复制的情况下,会判定事务之间无关才可以进行并行的数据传输,也就可能导致一种情况,主从库两边的数据在写入到数据库表中的数据的顺序不同,从数据库的角度这是无害的,但从业务逻辑的角度,这是有害的。比如 A 表 和 B表,在数据写入后,A 先写 ,B 后写,且根据A的数值在程序中尽显B 的数值的更新,而如果采用了并行的传输,则可能导致 B 的值先期传入到从库,而应用程序验证B的值是否是A的值更新而来,则会导致应用程序错误,因为B 可能先写入到从库,A的值可能后写入到从库中,这就导致业务逻辑会出现异常。

问题3 :参数设置错误,导致主从主机某个时刻不一致

在MySQL中,的参数slave_parallel_workers 定义了从库的复制县城并行线程的工作量,默认这个值为0 ,为0说明从库是以串行的方式进行数据的执行,如果将这个值改为其他值后,从库会启动并行复制执行,从库延迟的情况会有好转,但就会引发我们上面说的问题,导致在某一个时间,主从数据不一,业务逻辑有可能错误的情况。同时还有一个参数slave_preserve_commit_order,这个参数控制事务的提交顺序,确保从库在并行执行事务时,保持事务的提交顺序与主库一致,如果将次参数设置为OFF,则会导致我们提到的问题,在某一个时刻,主从数据不一致的情况,或违反业务逻辑的情况出现。同时一定在slave_parallel_type中配置logical_clock,所以在此基础上要注意以上参数的设置,避免出现一些并行复制导致业务逻辑出错的情况。

说完这些问题,我们反过来说说怎么通过Binlog来发现事务操作中的大事务提交的问题,导致的性能问题,一般我们都是依靠监控来看这个问题,但我们如果想从Binlog中找到证据也是可以的,下面我们交给大家一个方法,通过mysqlbinlog 解析日志后,打印每个事务中的操作的行数的大小。

b17587ccf888d15e13b7a3909efa9be9.png

通过这样的awk来预处理BINLOG中的数据,将每个事务中的操作进行计算,且打印出来,方便发现一个事务中是否有一次性大量的插入,删除,或者更新来发现大事务在某个时间段是否发生。

下面是执行的结果和程序,从图中可以看到每个数据库操作的事务都统计了操作中执行了多少DELETE, INSERT , UPDATE等数字,可以通过数字来告知数据库操作中是否有大事务,比如一次性操作很多行的情况。
dff165070279a6f64b6e9fe1960dbe8f.png
mysqlbinlog --start-datetime="2024-09-20 10:00:00" --stop-datetime="2024-09-20 14:00:00"  --base64-output=decode-rows -vv binlog.001509 | awk 'BEGIN {s_type=""; s_count=0;count=0;insert_count=0;update_count=0;delete_count=0;flag=0;} {if(match($0, /#15.*Table_map:.*mapped to number/)) {printf "Timestamp : " $1 " " $2 " Table : " $(NF-4); flag=1} else if (match($0, /(### INSERT INTO .*..*)/)) {count=count+1;insert_count=insert_count+1;s_type="INSERT"; s_count=s_count+1;}  else if (match($0, /(### UPDATE .*..*)/)) {count=count+1;update_count=update_count+1;s_type="UPDATE"; s_count=s_count+1;} else if (match($0, /(### DELETE FROM .*..*)/)) {count=count+1;delete_count=delete_count+1;s_type="DELETE"; s_count=s_count+1;}  else if (match($0, /^(# at) /) && flag==1 && s_count>0) {print " Query Type : "s_type " " s_count " row(s) affected" ;s_type=""; s_count=0; }  else if (match($0, /^(COMMIT)/)) {print "[Transaction total : " count " Insert(s) : " insert_count " Update(s) : " update_count " Delete(s) : " delete_count "] n+----------------------+----------------------+----------------------+----------------------+"; count=0;insert_count=0;update_count=0; delete_count=0;s_type=""; s_count=0; flag=0} } ' > analyze_binlog.001509.log

mysqlbinlog --start-datetime="2024-09-20 10:00:00" --stop-datetime="2024-09-20 14:00:00"  --base64-output=decode-rows -vv binlog.001509 | awk 'BEGIN {s_type=""; s_count=0;count=0;insert_count=0;update_count=0;delete_count=0;flag=0;} {if(match($0, /#15.*Table_map:.*mapped to number/)) {printf "Timestamp : " $1 " " $2 " Table : " $(NF-4); flag=1} else if (match($0, /(### INSERT INTO .*..*)/)) {count=count+1;insert_count=insert_count+1;s_type="INSERT"; s_count=s_count+1;}  else if (match($0, /(### UPDATE .*..*)/)) {count=count+1;update_count=update_count+1;s_type="UPDATE"; s_count=s_count+1;} else if (match($0, /(### DELETE FROM .*..*)/)) {count=count+1;delete_count=delete_count+1;s_type="DELETE"; s_count=s_count+1;}  else if (match($0, /^(# at) /) && flag==1 && s_count>0) {print " Query Type : "s_type " " s_count " row(s) affected" ;s_type=""; s_count=0; }  else if (match($0, /^(COMMIT)/)) {print "[Transaction total : " count " Insert(s) : " insert_count " Update(s) : " update_count " Delete(s) : " delete_count "] n+----------------------+----------------------+----------------------+----------------------+"; count=0;insert_count=0;update_count=0; delete_count=0;s_type=""; s_count=0; flag=0} } ' > analyze_binlog.001509.log

下面是类似的程序,但用另一种格式进行输出的

mysqlbinlog --base64-output=decode-rows -vv binlog.001509 | awk '
BEGIN {s_type=""; s_count=0;count=0;insert_count=0;update_count=0;delete_count=0;ddl_count=0;flag=0;ddl_flag=0;ddl_time="";}
{
    if(match($0, /#15.*Table_map:.*mapped to number/)) {
        printf "Timestamp : " $1 " " $2 " Table : " $(NF-4);
        flag=1;
    } 
    else if (match($0, /(### INSERT INTO .*..*)/)) {
        count=count+1;
        insert_count=insert_count+1;
        s_type="INSERT"; 
        s_count=s_count+1;
    }  
    else if (match($0, /(### UPDATE .*..*)/)) {
        count=count+1;
        update_count=update_count+1;
        s_type="UPDATE"; 
        s_count=s_count+1;
    } 
    else if (match($0, /(### DELETE FROM .*..*)/)) {
        count=count+1;
        delete_count=delete_count+1;
        s_type="DELETE";
        s_count=s_count+1;
    }
    else if (match($0, /ALTER TABLE/)) {
        ddl_count=ddl_count+1;
        ddl_flag=1;
    }
    else if (match($0, /^(# at) /) && flag==1 && s_count>0) {
        print " Query Type : "s_type " " s_count " row(s) affected" ;
        s_type="";
        s_count=0;
    }  
    else if (match($0, /^(COMMIT)/)) {
        if (ddl_flag==1) {
            print "[DDL Operation " ddl_count " at time " ddl_time "]";
            ddl_count=0;
            ddl_flag=0;
            ddl_time="";
        }
        print "[Transaction total : " count " Insert(s) : " insert_count " Update(s) : " update_count " Delete(s) : " delete_count "] n+----------------------+----------------------+----------------------+----------------------+"; 
        count=0;
        insert_count=0;
        update_count=0; 
        delete_count=0;
        s_type="";
        s_count=0;
        flag=0;
    }
    else if (ddl_flag==1 && match($0, /# at/)) {
        split($1, time_part, ":");
        ddl_time = time_part[1] ":" time_part[2] ":" time_part[3];
    }
}
'  > test.log

在Binlog方面可以动很多的脑子,比如分析DDL 操作,甚至简易的审计程序的数据来源等等,通过将日志进行解析,汇总,分析后可以得出很多可以有利用价值的分析结果,甚至可以通过分析将日志中的DDL语句进行打印,分析数据库DDL操作的历史等。

置顶文章:

开源不便宜,更贵 ?--从MariaDB被收购说起,“海豹”变成“金丝雀”

MySQL还用学吗?这谁问的 “好问题” !

MySQL 8.0x 到 9.0均可能崩溃--云厂商开发指责 MYSQL不测试就推新版本?

MySQL 让你还用5.7 出事了吧,用着用着5.7崩了

MySQL 8.0 小版本更新要点,那个小版本更稳定(8.0.24-8.0.37)

MySQL 8.0 版本更新 要点 列表 (8.0-8.0.23)

DBA 失职导致 PostgreSQL 日志疯涨

微软 “爱” 上PostgreSQL, PG  “嫁给” 微软!

撕逼!PostgreSQL 和 MongoDB 开撕,MySQL却躺枪

阿里云 安全扫描 ,说我PostgreSQL 自建主机极度不安全, 谁的问题?

PostgreSQL 13.0-13.15 功能更新和bug fixed列表

撕逼!PostgreSQL 和 MongoDB 开撕,MySQL却躺枪

往期热门文章:

PostgreSQL  哪些版本尽量避免使用,版本更新重点明晰(PG12)

PostgreSQL  15 16 小版本更新信息小结 版本更新是不是挤牙膏

PostgreSQL 14 小版本分析,有那个版本不建议使用

Windows 是MySQL和PostgreSQL高性能数据库的坟墓

PostgreSQL 具有createdb的用户无法创建数据库的原因(之一)

道歉贴,为最近写的一篇“垃圾贴”

PostgreSQL 同样的语句 一会快 一会慢到底怎么回事,

MongoDB  系统IOPS 告警系统处于崩溃,优化语句从1秒优化到1毫秒解决问题

云原生数据库是青出于蓝胜于蓝,还是数据库产品的倒退?

专访唐建法-从MongoDB中国第一人到TapData掌门人的故事

MySQL 8.0x 到 9.0均可能崩溃--云厂商开发指责 MYSQL不测试就推新版本?

DISS 阿里云 DAS数据库服务,阿里云数据库服务的毒瘤

临时工说:DBA 7*24H 给2万的工作,到底去不去?

PolarDB 最近遇到加字段加不上的问题 与 使用PolarDB 三年感受与恳谈

PostgreSQL 稳定性平台 PG中文社区大会--杭州来去匆匆

MySQL 让你还用5.7 出事了吧,用着用着5.7崩了

临时工访谈:问金融软件开发总监  哪些业务不用传统数据库

PolarDB  Serverless POC测试中有没有坑与发现的疑问

临时工访谈:PolarDB Serverless  发现“大”问题了  之 灭妖记 续集

临时工访谈:庙小妖风大-PolarDB 组团镇妖 之 他们是第一

PolarDB for PostgreSQL  有意思吗?有意思呀

PolarDB  Serverless POC测试中有没有坑与发现的疑问

MySQL 的SQL引擎很差吗?由一个同学提出问题引出的实验

临时工访谈:从国产数据库 到 普罗大众的产品 !与在美国创业软件公司老板对话

PostgreSQL 如何通过工具来分析PG 内存泄露

MySQL 的SQL引擎很差吗?由一个同学提出问题引出的实验

临时工访谈:我很普通,但我也有生存的权利,大龄程序员 求职贴

临时工说: 快速识别 “海洋贝壳类” 数据库方法速递

临时工说:国产 数据库 销售人员  图鉴

临时工说:DBA 是不是阻碍国产数据库发展的毒瘤 ,是不是?从国产

PostgreSQL   玩PG我们是认真的,vacuum 稳定性平台我们有了

临时工说:裁员裁到 DBA 咋办  临时工教你 套路1 2 3

PolarDB  搞那么多复杂磁盘计费的东西,抽筋了吗?

临时工说:OceanBase 到访,果然数据库的世界很卷,没边

MONGODB  ---- Austindatabases  历年文章合集

MYSQL  --Austindatabases 历年文章合集

POSTGRESQL --Austindatabaes 历年文章整理

POLARDB  -- Ausitndatabases 历年的文章集合

PostgreSQL  查询语句开发写不好是必然,不是PG的锅

SQL SERVER 如何实现UNDO REDO  和PostgreSQL 有近亲关系吗

MongoDB 2023纽约 MongoDB 大会 -- 我们怎么做的新一代引擎 SBE Mongodb 7.0双擎力量(译)

MongoDB 2023年度纽约 MongoDB 年度大会话题 -- MongoDB 数据模式与建模

MongoDB  双机热备那篇文章是  “毒”

MongoDB   会丢数据吗?在次补刀MongoDB  双机热备

临时工说:从人性的角度来分析为什么公司内MySQL 成为少数派,PolarDB 占领高处

POLARDB  到底打倒了谁  PPT 分享 (文字版)

PostgreSQL  字符集乌龙导致数据查询排序的问题,与 MySQL 稳定 "PG不稳定"

PostgreSQL  Patroni 3.0 新功能规划 2023年 纽约PG 大会 (音译)

Austindatabases 公众号,主要围绕数据库技术(PostgreSQL, MySQL, Mongodb, Redis, SqlServer,PolarDB, Oceanbase 等)和职业发展,国外数据库大会音译,国外大型IT信息类网站文章翻译,等,希望能和您共同发展。

截止今天共发布1225篇文章

671f2517780a58a2821dd6d7b7aebd95.png

302597fa67c6c0a8594a90ef1da6574e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值