搜索
首页数据库mysql教程MySQL中使用binlog时binlog格式的选择

mysql教程栏目介绍使用binlog时binlog格式的选择。

MySQL中使用binlog时binlog格式的选择

一、binlog的三种模式

1.statement level模式

每一条会修改数据的sql都会记录到master的bin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行。 优点:statement level下的优点,首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减少bin-log日志量,节约io,提高性能。因为他只需要记录在master上所执行的语句的细节,以及执行语句时候的上下文的信息。 缺点:由于它是记录的执行语句,所以为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端被执行的时候能够得到和在master端执行时候相同的结果。另外就是,由于mysql现在发展比较快,很多的新功能加入,使mysql的复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在statement level下,目前已经发现的就有不少情况会造成mysql的复制问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,比如sleep()在有些版本就不能正确复制。

2.rowlevel模式

日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改 优点:bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以row level的日志的内容会非常清楚的记录下每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题。 缺点:row level下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改记录,这样可能会产生大量的日志内容,比如有这样一条update语句:update product set owner_member_id='d' where owner_member_id='a',执行之后,日志中记录的不是这条update语句所对应的事件(mysql是以事件的形式来记录bin-log日志),而是这条语句所更新的每一条记录的变化情况,这样就记录成很多条记录被更新的很多事件。自然,bin-log日志的量会很大。

3.mixed模式

实际上就是前两种模式的结合,在mixed模式下,mysql会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在statement和row之间选一种。新版本中的statement level还是和以前一样,仅仅记录执行的语句。而新版本的mysql中对row level模式被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete 等修改数据的语句,那么还是会记录所有行的变更。

二、我们使用binlog时应该选择什么格式呢

通过上面的介绍我们知道了binlog_format为STATEMENT在一些场景下能够节省IO、加快同步速度,但是对于InnoDB这种事务引擎,在READ-COMMITTED、READ-UNCOMMITTED隔离级别或者参数innodb_locks_unsafe_for_binlog为ON时,禁止binlog_format=statement下的写入,同时对于binlog_format=mixed这种对于非事务引擎、其他隔离级别默认写statement格式的模式也只会记录row格式。

> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+

> create table t(c1 int) engine=innodb;

> set binlog_format=statement;

> insert into t values(1);
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.

> set binlog_format='mixed';

> show binlog events in 'mysql-bin.000004'\G
*************************** 3. row ***************************
   Log_name: mysql-bin.000002
        Pos: 287
 Event_type: Gtid
  Server_id: 3258621899
End_log_pos: 335
       Info: SET @@SESSION.GTID_NEXT= 'ed0eab2f-dfb0-11e7-8ad8-a0d3c1f20ae4:9375'
*************************** 4. row ***************************
   Log_name: mysql-bin.000002
        Pos: 335
 Event_type: Query
  Server_id: 3258621899
End_log_pos: 407
       Info: BEGIN
*************************** 5. row ***************************
   Log_name: mysql-bin.000002
        Pos: 407
 Event_type: Table_map
  Server_id: 3258621899
End_log_pos: 452
       Info: table_id: 124 (test.t)
*************************** 6. row ***************************
   Log_name: mysql-bin.000002
        Pos: 452
 Event_type: Write_rows_v1
  Server_id: 3258621899
End_log_pos: 498
       Info: table_id: 124 flags: STMT_END_F
*************************** 7. row ***************************
   Log_name: mysql-bin.000002
        Pos: 498
 Event_type: Xid
  Server_id: 3258621899
End_log_pos: 529
       Info: COMMIT /* xid=18422 */复制代码

为什么READ-COMMITTED(RC)、READ-UNCOMMITTED下无法使用statement格式binlog?这是因为语句在事务中执行时,能够看到其他事务提交或者正在写入的数据。事务提交后binlog写入,然后在从库回放,就会看到的数据会与主库写入时候不对应。 例如: 有表:

+------+------+
| a    | b    |
+------+------+
|   10 |    2 |
|   20 |    1 |
+------+------+复制代码

我们做如下操作:

  1. session1在事务中做update,UPDATE t1 SET a=11 where b=2;满足条件的有行(10,2)的一条记录,并未提交。
  2. session2也做update操作,将行(20,1)更新为(20,2)并提交。
  3. 然后前面的sesssion1提交对行(10,2)的更新。

如果binlog中使用Statement格式记录,在slave回放的时候,session2中的更新由于先提交会先回放,将行(20,1)更新为(20,2)。随后回放session1的语句UPDATE t1 SET a=11 where b=2;语句就会将更新(10,2)和(20,2)两行为(11,2)。这就导致主库行为(11, 2), (20,2),slave端为(11,2), (11, 2)。

三、问题分析

上面是通过一个具体的例子说明。本质原因是RC事务隔离级别并不满足事务串行化执行要求,没有解决不可重复和幻象读。

对于Repetable-ReadSerializable隔离级别就没关系,Statement格式记录。这是因为对于RR和Serializable,会保证可重复读,在执行更新时候除了锁定对应行还会在可能插入满足条件行的时候加GAP Lock。上述case更新时,session1更新b =2的行时,会把所有行和范围都锁住,这样session2在更新的时候就需要等待。从隔离级别的角度看Serializable满足事务的串行化,因此binlog串行记录事务statement格式是可以的。同时InnoDB的RR隔离级别实际已经解决了不可重复读和幻象读,满足了ANSI SQL标准的事务隔离性要求。

READ-COMMITTEDREAD-UNCOMMITTED的binlog_format限制可以说对于所有事务引擎都适用。

四、拓展内容

对于InnoDB RR和Serializable隔离级别下就一定能保证binlog记录Statement格式么?也不一定。在Innodb中存在参数innodb_locks_unsafe_for_binlog控制GAP Lock,该参数默认为OFF:

mysql> show variables like 'innodb_locks_unsafe_for_binlog';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_locks_unsafe_for_binlog | OFF   |
+--------------------------------+-------+
1 row in set (0.01 sec)复制代码

即RR级别及以上除了行锁还会加GAP Lock。但如果该参数设置为ON,对于当前读就不会加GAP Lock,即在RR隔离级别下需要加Next-key lock的当前读蜕化为READ-COMMITTED。所以如果此参数设置为ON时即便使用的事务隔离级别为Repetable-Read也不能保证从库数据的正确性。

五、总结

对于线上业务,如果使用InnoDB等事务引擎,除非保证RR及以上隔离级别的写入,一定不要设置为binlog_format为STATEMENT,否则业务就无法写入了。而对于binlog_format为Mixed模式,RR隔离级别以下这些事务引擎也一定写入的是ROW event。

更多相关免费学习推荐:mysql教程(视频)

以上是MySQL中使用binlog时binlog格式的选择的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:juejin。如有侵权,请联系admin@php.cn删除
MySQL中有哪些不同的存储引擎?MySQL中有哪些不同的存储引擎?Apr 26, 2025 am 12:27 AM

mysqloffersvariousStorageengines,每个suitedfordferentusecases:1)InnodBisidealForapplicationsNeedingingAcidComplianCeanDhighConcurncurnency,supportingtransactionsancions and foreignkeys.2)myisamisbestforread-Heavy-Heavywyworks,lackingtransactionsactionsacupport.3)记忆

MySQL中有哪些常见的安全漏洞?MySQL中有哪些常见的安全漏洞?Apr 26, 2025 am 12:27 AM

MySQL中常见的安全漏洞包括SQL注入、弱密码、权限配置不当和未更新的软件。1.SQL注入可以通过使用预处理语句防止。2.弱密码可以通过强制使用强密码策略避免。3.权限配置不当可以通过定期审查和调整用户权限解决。4.未更新的软件可以通过定期检查和更新MySQL版本来修补。

您如何确定MySQL中的慢速查询?您如何确定MySQL中的慢速查询?Apr 26, 2025 am 12:15 AM

在MySQL中识别慢查询可以通过启用慢查询日志并设置阈值来实现。1.启用慢查询日志并设置阈值。2.查看和分析慢查询日志文件,使用工具如mysqldumpslow或pt-query-digest进行深入分析。3.优化慢查询可以通过索引优化、查询重写和避免使用SELECT*来实现。

如何监视MySQL Server的健康和性能?如何监视MySQL Server的健康和性能?Apr 26, 2025 am 12:15 AM

要监控MySQL服务器的健康和性能,应关注系统健康、性能指标和查询执行。1)监控系统健康:使用top、htop或SHOWGLOBALSTATUS命令查看CPU、内存、磁盘I/O和网络活动。2)追踪性能指标:监控查询每秒数、平均查询时间和缓存命中率等关键指标。3)确保查询执行优化:启用慢查询日志,记录并优化执行时间超过设定阈值的查询。

比较和对比Mysql和Mariadb。比较和对比Mysql和Mariadb。Apr 26, 2025 am 12:08 AM

MySQL和MariaDB的主要区别在于性能、功能和许可证:1.MySQL由Oracle开发,MariaDB是其分支。2.MariaDB在高负载环境中性能可能更好。3.MariaDB提供了更多的存储引擎和功能。4.MySQL采用双重许可证,MariaDB完全开源。选择时应考虑现有基础设施、性能需求、功能需求和许可证成本。

MySQL的许可与其他数据库系统相比如何?MySQL的许可与其他数据库系统相比如何?Apr 25, 2025 am 12:26 AM

MySQL使用的是GPL许可证。1)GPL许可证允许自由使用、修改和分发MySQL,但修改后的分发需遵循GPL。2)商业许可证可避免公开修改,适合需要保密的商业应用。

您什么时候选择InnoDB而不是Myisam,反之亦然?您什么时候选择InnoDB而不是Myisam,反之亦然?Apr 25, 2025 am 12:22 AM

选择InnoDB而不是MyISAM的情况包括:1)需要事务支持,2)高并发环境,3)需要高数据一致性;反之,选择MyISAM的情况包括:1)主要是读操作,2)不需要事务支持。InnoDB适合需要高数据一致性和事务处理的应用,如电商平台,而MyISAM适合读密集型且无需事务的应用,如博客系统。

在MySQL中解释外键的目的。在MySQL中解释外键的目的。Apr 25, 2025 am 12:17 AM

在MySQL中,外键的作用是建立表与表之间的关系,确保数据的一致性和完整性。外键通过引用完整性检查和级联操作维护数据的有效性,使用时需注意性能优化和避免常见错误。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中