Mysql binlog的三种模式statement,row,mixed详解,以及无主键造成复制延时的测试

news2024/11/18 2:25:39

2.1  Statement 模式的概念
Statement 是基于语句的复制模式。
Statement 模式将数据库中执行的修改操作记录为 SQL 语句,再从数据库上执行相同的 SQL 语句来实现数据同步。

2.2  Statement 模式的优点
Statement 模式的优点是简单明了,易于理解和实现。

2.3  Statement 模式的缺点

Statement 模式在执行涉及非确定性函数、触发器和存储过程等操作时,可能会导致不一致的结果。

1)不支持 RU、RC 隔离级别;
2)binglog 日志文件中,上一个事物的结束点是下一个事物的开始点;
3)DML、DDL 语句都会明文显示;
4)对一些系统函数不能准确复制或者不能复制;
5)主库执行 delete from t1 where c1=xxx limit 1,statement 模式下,从库也会这么执行,可能导致删除的不是同一行数据;
6)主库有 id=1 和 id=10 两行数据,从库有 id=1,2,3,10 这四行数据,主库执行 delete from t1 where id<10 命令,从库删除过多数据。

2.4  Statement 模式的应用场景
Statement 模式适用于大多数情况下的数据库复制需求。

例如:
1)一次更新大量数据,如二十万数据。反之,在复制时,从库可能会追得太慢,然后导致延时;
2)使用 pt-table-checksum 工具时。


2.1  Row 模式的概念

MySQL 5.7 默认的日志模式为 Row。
Row 模式是基于行的复制模式,它将数据库中实际修改的行记录写入 Binlog ,从数据库通过解析 Binlog 来逐行执行相应的修改操作。
相对 statement ,Row 模式更加精确、安全,能够确保数据的一致性。
2.2  Row 模式的优点

Row 模式能准确复制修改的行记录,避免了语句复制模式下的不确定性问题。

2.3 Row 模式的缺点

如果 Binlog 文件较大,传输成本就会很高,在某些情况下,可能会导致性能下降。

1)在表有主键的情况下复制更加快;

2)系统的特殊函数也能复制;

3)更少的锁,只有行锁;

4)Binlog 文件比较大,假设单语句更新 20 万行数据,可能要半小时,也有可能把主库跑挂;

5)MySQL 5.6 之前的版本,无法从 binog 看见用户执行的 SQL 语句;

6)DDL 语句明文显示,DML 语句加密显示;

7)DML 经过 base64 加密,需要使用参数 --base64-output=decode-rows --verbose;

8)update 修改的语句可以看到历史旧数据。
2.4  Row 模式的应用场景

Row 模式适用于对数据一致性要求较高的场景,特别是涉及一些复杂的数据库操作和业务逻辑。例如,涉及触发器、存储过程和函数等的数据库操作。

使用Row 模式时需注意,Row 模式可能导致 Binlog 文件较大,需要合理设置 Binlog 文件大小和保留时间。

3.1  Mixed 模式的概念

Mixed 模式(混合模式)是将语句复制模式和行复制模式结合起来使用。

大多数的修改操作,通常使用 Statement 模式记录对应的 SQL 语句。

一些特殊的操作,涉及非确定性函数和存储过程等,则使用 Row 模式记录修改的行记录。

3.2  Mixed 模式的优缺点

Mixed 模式综合了语句复制模式和行复制模式的优点,能够在大多数情况下高效地记录修改操作,并在需要时使用行复制模式确保数据的准确性。

但 Mixed 模式对一些特殊操作的处理可能会很复杂,需要特别注意下配置和管理。

我们来测试下没有主键的情况下,从库复制延时情况:
主库:创建无主键的表log_test然后用存储过程插入4000000行数据:
delimiter //
drop procedure if exists insert_log_test;
create procedure insert_log_test()
begin
    declare i int;
    set i = 0;
     start transaction;
    while i < 1000000 do
        insert into log_test values (i,'中间提交的事务+++++++++**********++++++++');
        insert into log_test values (i,'中间提交的事务+++++++++**********++++++++');
       insert into log_test values (i,'中间提交的事务+++++++++**********++++++++');
       insert into log_test values (i,'中间提交的事务+++++++++**********++++++++');
        set i = i + 1;
    end while;
    commit;

end//
delimiter ;
mysql> call insert_log_test();
Query OK, 0 rows affected (1 min 17.62 sec)

mysql> select count(*) from log_test;
+----------+
| count(*) |
+----------+
|  4000000 |
+----------+
1 row in set (2.10 sec)

mysql> update log_test set id=id+80000000;
Query OK, 4000000 rows affected (17.84 sec)
Rows matched: 4000000  Changed: 4000000  Warnings: 0

备库:可以看到Seconds_Behind_Master一直在增大
[root@localhost:mytest1]>show slave status\G;

          Exec_Master_Log_Pos: 1012007859
              Relay_Log_Space: 1453954904
        Seconds_Behind_Master: 431

可以看到5分钟的时间,更新了不到10000行数据,追平主库需要大概5分钟*400=20000分钟=330小时=14天。。。。。

[root@localhost:mytest1]>select now();
+---------------------+
| now()               |
+---------------------+
| 2023-09-11 16:13:38 |
+---------------------+
1 row in set (0.00 sec)

[root@localhost:mytest1]>select count(*) from log_test where id>80000000;
+----------+
| count(*) |
+----------+
|    39629 |
+----------+
1 row in set (2.59 sec)

[root@localhost:mytest1]>select now();
+---------------------+
| now()               |
+---------------------+
| 2023-09-11 16:18:38 |
+---------------------+
1 row in set (0.00 sec)

[root@localhost:mytest1]>select count(*) from log_test where id>80000000;
+----------+
| count(*) |
+----------+
|    48282 |
+----------+
1 row in set (2.29 sec)

那存在主键,只存在普通索引和无任何索引三种情况,延时的不同以及原理是什么呢?

那存在主键,只存在普通索引和无任何索引三种情况,延时的不同以及原理是什么呢?
1)只存在普通索引:
从库应用的时候会重新评估应该使用哪个索引,优先使用主键和唯一键。因为表只有一个普通索引key,对于Event中的每条数据都需要进行索引定位操作,并且对于非唯一索引来讲第一次返回的第一行数据可能并不是删除的数据,可能还需要继续扫描下一行。大概的流程如图:

2)存在主键:

主库执行时会首先利用主键,只需要一次索引定位,然后顺序扫描接下来的数据进行更新就可以了。大概的流程如图:

3)不存在任何索引

如果表上一个索引都没有的话,从库执行的每个event都要进行全表扫描,代价非常大,这也是表上没有索引从库会有比较大同步延迟的关键原因。大概的流程图:

我们来实际测试一下,存在主键的情况下,从库追日志的性能提高多少,测试结果:等主库Update完成后,立即在从库查询,就发现已经追平了,由此可见主键的对提升性能的重要性。

主:
delimiter //
drop procedure if exists insert_log_test;
create procedure insert_log_test()
begin
    declare i int;
    set i = 0;
     start transaction;
    while i < 1000000 do
        insert into log_test_new values (default,i,'中间提交的事务+++++++++**********++++++++');
        insert into log_test_new values (default,i,'中间提交的事务+++++++++**********++++++++');
       insert into log_test_new values (default,i,'中间提交的事务+++++++++**********++++++++');
       insert into log_test_new values (default,i,'中间提交的事务+++++++++**********++++++++');
        set i = i + 1;
    end while;
    commit;

end//
delimiter ;

mysql> create table log_test_new(id_primary INT PRIMARY KEY AUTO_INCREMENT,id int,name VARCHAR(100));
Query OK, 0 rows affected (0.01 sec)

mysql> source /home/mysql/liys/insert_log_test.sql;
Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> call insert_log_test();
Query OK, 0 rows affected (1 min 18.90 sec)

update log_test_new set id=id+80000000;


从:从库很快就追平了日志,等主库Update完成后,立即在从库查询,就发现已经追平了,由此可见主键的对提升性能的重要性。


[root@localhost:mytest1]>select count(*)  from log_test_new where id>=80000000;
+----------+
| count(*) |
+----------+
|  4000000 |
+----------+
1 row in set (1.45 sec)

[root@localhost:mytest1]>select * from log_test_new where id=80000000;          
+------------+----------+--------------------------------------------------+
| id_primary | id       | name                                             |
+------------+----------+--------------------------------------------------+
|          1 | 80000000 | 中间提交的事务+++++++++**********++++++++        |
|          2 | 80000000 | 中间提交的事务+++++++++**********++++++++        |
|          3 | 80000000 | 中间提交的事务+++++++++**********++++++++        |
|          4 | 80000000 | 中间提交的事务+++++++++**********++++++++        |
+------------+----------+--------------------------------------------------+
4 rows in set (1.67 sec)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1001748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工作不好找,普通打工人如何破局

大家好&#xff0c;我是苍何&#xff0c;我的一位阿里朋友被裁后&#xff0c;找工作找了一个月都没结果&#xff0c;很多到最后一面被pass了&#xff0c;不由得做一下感慨&#xff0c;即使是大厂背景又如何&#xff0c;面对经济环境和大环境市场&#xff0c;每个人都不容易。 …

关于一个left join的易错点

很多人在学习mysql的时候应该都出现过很多问题&#xff0c;特别是连接方面的问题应该最多&#xff0c;希望这篇文章帮助到正在找bug的你 Java报错数据返回数量出现错误 遇到这种问题一定要看日志 很明显通过left join查询除了两条数据并且为空 马上思考错误的原因&#xff0c;…

【playwright】访问不同链接方法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 访问不同页面方法方法比较 browser.new_page() page context.new_page() 1. 访问不同url 1.1 方法一 browser.new_page() 打开多个浏览器&#xff0…

JS如何判断一个变量是否为数组类型?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用 Array.isArray() 方法⭐ 使用 instanceof 操作符⭐ 使用 Object.prototype.toString.call() 方法⭐ 使用 Array.from() 方法⭐ 使用 Array.prototype.isArray 属性&#xff08;不推荐&#xff09;⭐ 写在最后 ⭐ 专栏简介 前端入门之…

人机融合的熵增定律

在信息论中&#xff0c;熵增定律是指在信息传输或处理过程中&#xff0c;总的熵&#xff08;即不确定性或信息的度量&#xff09;通常会增加。然而&#xff0c;对于人机融合的情况&#xff0c;熵增定律并不是一个普适的定律&#xff0c;而是取决于具体情境和应用。 当人与机器进…

uniapp-小程序登录授权框

微信官方文档 不弹出授权框原因 因为版本问题&#xff0c;目前的最新的版本是不支持 wx.getUserInfo 去主动弹出授权框 只能引导用户去点击 butten 去授权 解决方法 我的思路是参考了其他的微信微信小程序, 就是跳转到我的页面的时候 在钩子函数内去触发一个封装的模态框,状…

STM32-HAL库07-软件SPI驱动0.96寸OLED

STM32-HAL库07-软件SPI驱动0.96寸OLED 一、所用材料&#xff1a; STM32VGT6自制控制板 STM32CUBEMX&#xff08;HAL库软件&#xff09; MDK5 二、所学内容&#xff1a; 通过HAL库配置四个GPIO输出口&#xff0c;对其进行软件模拟SPI发送规则&#xff0c;进而驱动OLED进行数…

VisualStudio Code 支持C++11插件配置

问题 Visual Studio Code中的插件: Code Runner 支持运行C、C、Java、JS、PHP、Python等多种语言。 但是它不支持C11特性的一些使用&#xff0c;比如类似错误&#xff1a; binarySearch.cpp:26:17: error: non-aggregate type ‘vector’ cannot be initialized with an ini…

C++(day4)

思维导图 封装Mystring #include <iostream> #include<cstring>using namespace std;class Mystring{ public://无参构造函数Mystring():size(10){strnew char[size];strcpy(str,"");cout<<"无参构造函数"<<endl;}//有参构造函数…

前端内存泄漏和溢出的情况以及解决办法

写在前面&#xff1a; 在平时写代码时&#xff0c;内存泄漏的情况会时有发生&#xff0c;虽然js有内存回收机制&#xff0c;但在平时编程中还是需要注意避免内存泄漏的情况&#xff1b;前几天做移动端时遇到一个内存泄漏造成移动端页面卡顿的问题&#xff0c;所以想总结下前端…

GO语言网络编程(并发编程)Channel

GO语言网络编程&#xff08;并发编程&#xff09;Channel 1、Channel 1.1.1 Channel 单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。 虽然可以使用共享内存进行数据交换&#xff0c;但是共享内存在不同的goroutine中容易发生竞态…

Linux Debian12使用git将本地项目打标签、创建分支和分支合并到master再上传到码云(gitee)远程仓库

一、git创建分支并克隆指定分支到本地 gitee官网&#xff1a;https://gitee.com/ 登录上gitee账号,我这用test仓库作测试。新建分支名称为develop&#xff0c;分支起点选择master&#xff0c;创建即可&#xff0c;如下图所示&#xff1a; 使用git管理代码版本时&#xff0…

SpringBoot 中的事务管理讲解

Spring Boot 中的事务管理 在实际的开发中&#xff0c;事务是非常重要的一个概念。在 Spring Boot 中&#xff0c;我们可以使用事务管理器来管理事务。事务管理器可以确保一系列操作要么全部成功&#xff0c;要么全部失败&#xff0c;从而保证数据的一致性和完整性。在本文中&…

音频驱动嘴型的视频数字人虚拟主播工具motionface replay使用教程

音频驱动嘴型的视频数字人虚拟主播工具motionface replay使用教程 1&#xff1a;系统要求 软件运行支持32位/64位window 10/11系统&#xff0c;内存最低要求> 8Gb.无其他硬性要求。 1&#xff1a;下载安装 打开百度网盘链接下载&#xff1a; 链接&#xff1a;百度网盘 请输入…

unityhub登录不上,登录界面刷新不出来, 或检测不到Unity

如果是登录界面白屏的话 或 检测不到Unity 可以尝试 1.关闭hub&#xff08;右下角也要退出&#xff0c;找不到的可以直接任务管理器退出&#xff09; 2.删除 %UserProfile%\AppData\Roaming 里面的 \UnityHub\Cache和\Unity\Caches 文件夹 C:\Users\Administrator\AppData\Ro…

Linkstech多核并行仿真丨光伏发电系统模型及IEEE 39 bus模型多核并行实测

新能源场站和区域电网作为复杂且具有动态特性的大规模电力系统&#xff0c;需要实时仿真测试来验证其性能、稳定性和响应能力。在这种背景下&#xff0c;多核并行仿真运算显得尤为重要。多核并行仿真能够同时处理电力系统的复杂模型&#xff0c;加速仿真过程&#xff0c;实现接…

C#自定义控件组件实现Chart图表(多Y轴,选择图例加粗,选择放大,缩放,点击查看信息等功能)

先看看ECharts的效果 C# 工具箱里的Chart控件就不演示了,很多效果没办法做出来,做出来效果也很不理想。所以,需要自己去手动实现工具箱里的Chart没办法实现的效果; 先看看实现后的效果 绑定数据 点击图表 点击右侧图例加粗 选择放大 右键 点击缩小,恢复

Docker Desktop使用宿主机Windows的配置文件持久化存储数据

《微软官网Windows 上的 Docker 引擎帮助文档》 以Nginx为例 拉取Nginx镜像 docker pull nginx:1.23.1先启动Nginx&#xff0c;然后把Nginx的配置文件复制到Windows docker run --namenginx-1.23.1 -d -p 80:80 nginx:1.23.1把Nginx的配置文件复制到Windows 注意&#xff1…

【算法训练-数组 四】【合并】:合并两个有序数组

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【数组合并】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

【深度学习】分类损失函数解析

【深度学习】分类相关的损失解析 文章目录 【深度学习】分类相关的损失解析1. 介绍2. 解析3. 代码示例 1. 介绍 在分类任务中&#xff0c;我们通常使用各种损失函数来衡量模型输出与真实标签之间的差异。有时候搞不清楚用什么&#xff0c;下面是几种常见的分类相关损失函数及其…