总体来说:在 tx_isolation= READ-COMMITTED 、binlog_format =statement 的情况下,mysql 没有gap 锁,这样binlog 记录的数据修改的顺序可能会导致 复制环境的 slave 数据和master 数据不一致。

模拟步骤

数据初始化

 CREATE TABLE `gapt` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ind_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
mysql> select * from gapt;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 10 | 10 |
| 11 | 11 |
| 15 | 15 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 8 | 8 |
| 9 | 9 |
+----+------+

session1 和 session2 模拟

@session 1:
mysql> show variables like '%tx_isolation%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update gapt set id=name+20 where name between 5 and 11;
Query OK, 6 rows affected (0.00 sec)
Rows matched: 6 Changed: 6 Warnings: 0 @session2
mysql> show variables like '%tx_isolation%';
+---------------+----------------+
| Variable_name | Value |
+---------------+----------------+
| tx_isolation | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into gapt select 24,5;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> system date
Fri Jun 19 10:55:38 CST 2015 @session1
mysql> select * from gapt where name between 5 and 11;
+----+------+
| id | name |
+----+------+
| 30 | 10 |
| 31 | 11 |
| 24 | 5 |
| 25 | 5 |
| 26 | 6 |
| 28 | 8 |
| 29 | 9 |
+----+------+
7 rows in set (0.00 sec) #你会发现 6行变成7行了,
mysql> system date;
Fri Jun 19 10:55:50 CST 2015
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

重点: 两个 session 执行完 commit,并且按照 binlog_format = statement 日志模式的话,那么最终的binlog日志记录应该是按照事务 commit 的顺序记录的。

#binlog 实际存储的执行顺序
@session2
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into gapt select 24,5;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.00 sec) #session1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update gapt set id=name+20 where name between 5 and 11;
Query OK, 6 rows affected (0.00 sec)
mysql> commit;

如果是这样记录的话你会发现这个 @session1 的 update 语句会把 session2 刚刚插入的 name='5',id=24 数据也会更新掉了!!这也就导致了(如果有复制)从库从库的数据就会和复制的主库不一样了!!

问题来了,我是如何模拟的呢?我是设置 tx_isolation=READ-COMMITTED binlog_format= MIXED 的时候,上面的操作可以正确执行,这是因为 MySQL 识别到了这个可能存在不一致的复制情况,就把上面的操作转换成了 binlog_format=row 的二进制日志。

#150619 10:55:00 server id 4306  end_log_pos 283        Table_map: `repl`.`gapt` mapped to number 52
#150619 10:55:00 server id 4306 end_log_pos 319 Write_rows: table id 52 flags: STMT_END_F
BINLOG '
hISDVRPSEAAALgAAABsBAAAAADQAAAAAAAEABHJlcGwABGdhcHQAAgMPAmAAAg==
hISDVRfSEAAAJAAAAD8BAAAAADQAAAAAAAEAAv/8GAAAAAE1
'/*!*/;
# at 319
#150619 10:55:09 server id 4306 end_log_pos 346 Xid = 447 #session2 的 commit
COMMIT/*!*/;
# at 346
#150619 10:57:04 server id 4306 end_log_pos 414 Query thread_id=16 exec_time=0 error_code=0
SET TIMESTAMP=1434682624/*!*/;
BEGIN
/*!*/;
# at 414
# at 460
#150619 10:54:14 server id 4306 end_log_pos 460 Table_map: `repl`.`gapt` mapped to number 52
#150619 10:54:14 server id 4306 end_log_pos 578 Update_rows: table id 52 flags: STMT_END_F
BINLOG '
VoSDVRPSEAAALgAAAMwBAAAAADQAAAAAAAEABHJlcGwABGdhcHQAAgMPAmAAAg==
VoSDVRjSEAAAdgAAAEICAAAAADQAAAAAAAEAAv///AUAAAABNfwZAAAAATX8BgAAAAE2/BoAAAAB
NvwIAAAAATj8HAAAAAE4/AkAAAABOfwdAAAAATn8CgAAAAIxMPweAAAAAjEw/AsAAAACMTH8HwAA
AAIxMQ==
'/*!*/;
# at 578
#150619 10:57:04 server id 4306 end_log_pos 605 Xid = 443 #session1 的 commit
COMMIT/*!*/;

binlog_format 为什么转化为 row 就可以呢,因为 row 格式的日志记录的是底层数据真正的变化,这样就不会导致复制环境的主从数据不一致了。

ps: 如果有什么理解错误的,或者模拟的不合理的地方,麻烦纠正指出来,谢谢。

mysql rc模式时binlog_format=row的解释【转】的更多相关文章

  1. mysql 5.7配置项最详细的解释

    配置样例 首先提供一个我使用的配置样例 [client] #password=88888888 socket=/data/var/mysql/mysql.sock [mysqld_safe] pid- ...

  2. mysql 主从模式总结(一)

    1. 主从模式的部署步骤 目标:部署一个有3台主机的单主模式的MySQL分组. Primary:192.168.197.110. Secondary:192.168.197.111. Secondar ...

  3. MySQL Binlog--MIXED模式下数据更新

    在 Mixed 模式下,MySQL 会根据执行的每一条具体的 SQL 语句来区分对待记录的日志形式,也就是在 statement 和 row 之间选择一种.如果SQL语句为UPDATE/DELETE等 ...

  4. mysql查询更新时的锁表机制分析

    为了给高并发情况下的mysql进行更好的优化,有必要了解一下mysql查询更新时的锁表机制. 一.概述 MySQL有三种锁的级别:页级.表级.行级.MyISAM和MEMORY存储引擎采用的是表级锁(t ...

  5. RR模式下利用区间锁防止幻读,RC模式没有区间锁会出现幻读

    Session 1: mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> select * from ...

  6. mysql READ-COMMITTED 模式下 行锁不会升级到表级锁

    mysql> select sn,id,info from s100 group by id; +-----+------+------+ | sn | id | info | +-----+- ...

  7. mysql bin-logrow模式,base64转正常sql

    可以通过以下命令查看日志是否开启查看 show global variables like '%log%'; 当bin-log的模式设置为row时 不仅日志长得快 , 并且查看执行的sql时 , 也稍 ...

  8. mysql查询更新时的锁表机制分析(只介绍了MYISAM)

    为了给高并发情况下的mysql进行更好的优化,有必要了解一下mysql查询更新时的锁表机制. 一.概述 MySQL有三种锁的级别:页级.表级.行级.MyISAM和MEMORY存储引擎采用的是表级锁(t ...

  9. MySql 严格模式相关配置

    目录 MySql 严格模式 MySQL的sql_mode合理设置 sql model 常用来解决下面几类问题 sql_mode常用值 注意 改为严格模式后可能会存在的问题 模式设置和修改(以解决上述问 ...

随机推荐

  1. Select算法(最坏复杂度O(n))

    #include<iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm&g ...

  2. express基础

    express框架 const express = require("express"); 引入express框架 var app= express(); 实例化   相当于构造函 ...

  3. FBV和CBV区别

    FBV和CBV区别         def dispatch(self, request, *args, **kwargs):        # 做分发的        if request.meth ...

  4. JS 更新

    JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECM ...

  5. 并发工具类(三)控制并发线程的数量 Semphore

    前言   JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...

  6. tcpdump抓sql语句

    -A -n -i any |grep --color 'system_type' -n2 -- -E..,.@.@.f........ ...Ndh-....GP..:A.............. ...

  7. python实现列表页数据的批量抓取练手练手的

    python实现列表页数据的批量抓取,练手的,下回带分页的 #!/usr/bin/env python # coding=utf-8 import requests from bs4 import B ...

  8. [python爬虫] 爬取图片无法打开或已损坏的简单探讨

    本文主要针对python使用urlretrieve或urlopen下载百度.搜狗.googto(谷歌镜像)等图片时,出现"无法打开图片或已损坏"的问题,作者对它进行简单的探讨.同时 ...

  9. UI5-文档-4.12-Shell Control as Container

    现在我们使用shell控件作为应用程序的容器,并使用它作为新的根元素.shell通过在桌面屏幕上引入一个所谓的信箱,来负责应用程序对设备屏幕大小的视觉调整. Preview The app is no ...

  10. RxJava 与观察者模式

    RxJava到底是什么?让我们直接跳过官方那种晦涩的追求精确的定义,其实初学RxJava只要把握两点:观察者模式和异步,就基本可以熟练使用RxJava了. 异步在这里并不需要做太多的解释,因为在概念和 ...