由于二进制日志是公共资源,所有线程都要写二进制日志,所以一定要避免两个线程同时更新二进制日志。因此,在事件组写二进制日志时,二进制日志将获得一个互斥锁LOCK_log,然后在事件组写完后释放,由于服务器所有的会话都向二进制日志写事务,所以这个锁经常会阻塞某些会话线程

1 写入DML语句

通常是指DELETE/INSERT/UPDATE语句,为保证一致性,MySQL在写入二进制日志时同时获得事务级锁,写完后释放锁

在表上锁释放前,在语句提交前同时需要将该语句写入二进制日志,这样就保证了二进制日志始终与语句对表的改动保持一致,如果记录日志没有作为语句的一部分时,有可能其他语句会插在这条语句对数据库的修改和记录二进制两个动作中间。

2 写入DDL语句

通常指的是CREATE TABLE/ALTER TABLE语句,DDL语句会在文件系统中创建或改变对象。为了保护表中的内部数据结构(.frm)得到更新,在修改表定义钱需要先获得一个内部锁LOCK_open

3 写入查询

对于SBR来说,最常见的就binlog事件就是QUERY事件,它将master上执行的语句写入日志,除了实际执行的语句本身,该语句还包含执行语句需要的附加信息

对服务器执行语句时必须知道隐式,隐式包括

1)当前数据库

向QUERY事件添加一个特殊字段,记录当前数据库,处理LOAD DATA INFILE语句的事件也有这个字段。

2)当前时间

有5个函数需要利用到时间NOW CURDATE CURTIME UNIX_TIMESTAMP SYSDATE,前4个返回开始执行的时间,而SYSDATE返回函数执行时的时间。

[root@localhost][(none)]> SELECT SYSDATE(),NOW(),SLEEP(2),SYSDATE(),NOW();
+---------------------+---------------------+----------+---------------------+---------------------+
| SYSDATE() | NOW() | SLEEP(2) | SYSDATE() | NOW() |
+---------------------+---------------------+----------+---------------------+---------------------+
| 2017-03-29 08:08:37 | 2017-03-29 08:08:37 | 0 | 2017-03-29 08:08:39 | 2017-03-29 08:08:37 |
+---------------------+---------------------+----------+---------------------+---------------------+
1 row in set (2.05 sec)

为了正确处理时间,事件将存储一个时间戳,表明事件何时开始执行的。然后将这个时间戳的值从事件复制到SLAVE执行进程,在计算时间函数的时候,将这个时间戳作为事件开始执行的时间

SYSDATE直接从操作系统获取时间,这个对于SBR来说是不安全的,有可能会导致master和slave上执行的返回值不一样。最好慎用这个函数

3)上下文

有些语句也包含隐式信息,需要满足一些条件

a)语句包含对用户定义变量的引用

b)包含RAND函数调用

c)包含LAST_INSERT_ID调用

d)需要向表中插入AUTO_INCREMENT类型的字段

无论上述那种情况,在写入包含查询时间之前,需要向二进制日志写入一个或多个上下文事件,由于一个QUERY事件之前可能有多个上下文时间,所以二进制日志同时要处理多个用户定义变量和RAND函数。二进制日志通过下面事件来存储必要的上下文信息

User_var 记录单个用户自定义变量的变量名及其值

Rand 记录RAND函数的随机数种子,种子取自会话颞部状态

Intvar 如果语句要插入AUTO_INCREMENT类型字段,在执行插入语句钱,该事件会设置表中自动增量计算器的值,如果语句包含LAST_INSERT_ID函数调用,该事件记录这个函数在该语句中的返回值

[root@localhost][(none)]> set @foo=12;
Query OK, 0 rows affected (0.00 sec) [root@localhost][(none)]> set @bar = 'fdjkfjdjfkdjfkdf';
Query OK, 0 rows affected (0.00 sec)
[root@localhost][(none)]> use boss
Database changed
[root@localhost][boss]> create table t1(b int auto_increment primary key,c varchar(20));
Query OK, 0 rows affected (0.43 sec)
[root@localhost][boss]> insert into t1(b,c) values(@foo,@bar),(RAND(),'random');
Query OK, 2 rows affected (0.11 sec)
Records: 2 Duplicates: 0 Warnings: 0 [root@localhost][boss]> insert into t1(b) values(LAST_INSERT_ID());
ERROR 1062 (23000): Duplicate entry '' for key 'PRIMARY'
[root@localhost][boss]> insert into t1(b) values(LAST_INSERT_ID()+1);
Query OK, 1 row affected (0.07 sec)
[root@localhost][boss]> show master status;
+------------------+----------+--------------+------------------+--------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+--------------------------------------------+
| mysql_bin.000023 | 2878 | | | a0c06ec7-fef0-11e6-9f85-525400a7d662:1-193 |
+------------------+----------+--------------+------------------+--------------------------------------------+
1 row in set (0.00 sec) [root@localhost][boss]> show binlog events in 'mysql_bin.000023'\G;

4)线程ID

二进制日志偶尔需要的最后一个隐式信息是处理语句的MySQL会话的线程ID,如果用了某些依赖的,例如CONNECTION_ID,就必须知道线程ID,当然,处理临时表,线程ID额外重要

服务器内部通过晦涩的表名来定义临时表(不同的会话中,允许同事存在两个同名的临时表),临时表的名字由服务器进程ID、创建表的线程ID和线程计数器组成(该计数器用来区分同一个线程不同的临时表实例),这种命名方式能够区分不同线程

创建的表,但是只有当线程ID被存入到二进制日志,语句才能访问相应的表

与二进制日志类似,线程ID也作为一个独立的字段存储在每个Query事件中,因此可以用线程ID字段来计算线程特定的数据,并正确处理临时表

写Query事件时,其线程ID是从服务器变量pseudo_thread_id中读取。也就是这个值可以在执行语句前设置,但需要有super权限,服务器变量也可以用于mysqlbinlog工具发出正确的命令,但通常不这么用

如果语句中包含CONNECTION_ID函数调用,或是创建了临时表,则Query事件在二进制日志中被标记为线程特定的。而Query事件总是包含线程ID,所以这个标记并不是必须的,主要目的是为了避免mysqlbinlog中不必要的pseudo_thread_id变量赋值

MySQL将语句写入到binlog二进制日志中的更多相关文章

  1. MySQL备份方案-->(利用mysqldump以及binlog二进制日志)

                                                         MySQL备份方案-->(利用mysqldump以及binlog二进制日志) 随着数据不 ...

  2. MySQL二进制日志中保存的上下文信息

    1.二进制日志中要保存上下文的原因 二进制日志是要在slave端重放的,记录上下文信息,是为了保证主丛数据库的一致.如rand一个随机数,在主上返回的可以有是100,在从上返回的可能就是1000了. ...

  3. 涉及到复制和二进制日志中的选项和变量-Replication and Binary Logging Options and Variables

    在搭建复制中,有些参数需要我们留意,在这里罗列出来,供大家参考一下,以GTID为基础 --server-id server-id:这是一个全局的可动态调整的变量,取值范围为0-4294967295,也 ...

  4. Mysql binlog二进制日志

    Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的实际原sql语句都会被记录在binlog中. 优点:不需要记录每一 ...

  5. MySQL完全备份脚本:数据+二进制日志+备份日志

    一. 脚本须知 1.mysql数据文件和二进制日志文件最好保存在不同的分区或存储设备上 2.备份完成后注意修改数据的权限以防止泄露重要信息,哪些主机哪些用户可以用来恢复 3. 查看导出的2进制日志文件 ...

  6. mysqlbinlog抽取二进制日志中某库某表的日志

    1.先使用myqlbinlog命令把整个库的二进制日志抽取出来 mysqlbinlog --database=db_name mysql-bin.xxxxxx > db_name.sql 2.然 ...

  7. mysql将语句写入表中

    使用create table语句即可 CREATE TABLE membertmp (select a.* from member as a where a.phone <> '' and ...

  8. MySQL二进制日志备份和恢复详解

    原文链接:http://www.showerlee.com/archives/681 ****经实践,该教程ok,特在此分享**** 基本概念 定义: 二进制日志包含了所有更新了数据或者已经潜在更新了 ...

  9. mysql之 日志体系(错误日志、查询日志、二进制日志、事务日志、中继日志)

    一. mysql错误日志:错误日志记录的事件:a).服务器启动关闭过程中的信息b).服务器运行过程中的错误信息c).事件调试器运行一个事件时间生的信息d).在从服务器上启动从服务器进程时产生的信息lo ...

随机推荐

  1. 灰色预测--matlab&python实现

    function SGrey X0 = input('请输入原始负荷数据:'); %输入原始数据 n = length(X0); %原始n年数据 %累加生成 X1 = zeros(1,n); for ...

  2. Fiddler4插件开发实践

    Fiddler4 是一款 巴拉巴拉..... 连接在这:http://www.telerik.com/fiddler 开发文档在这:http://docs.telerik.com/fiddler/Ex ...

  3. 获取表数据的插入SQL

    DECLARE @TABLE_NAME VARCHAR(200) SET @TABLE_NAME = 'myFunction' --表名 DECLARE @TABLE_CONDITION VARCHA ...

  4. Vue 获取验证码倒计时组件

    子组件 <template> <a class="getvalidate":class="{gray: (!stop)}"@click='cl ...

  5. 自己动手制作更好用的markdown编辑器-01

    这里文章都是从个人的github博客直接复制过来的,排版可能有点乱. 原始地址  http://benq.im   文章目录 1. 简介 2. 项目结构 3. 程序主界面 4. 拖动窗口 5. app ...

  6. mac os x 使用scp取代sz rz

    在windows下,能够通过secureCRT的sz来下载文件,而用rz来上传文件.在unix/linux下则不必.由于scp命令能够完毕这项目工作. sz file替代方案为:scp usernam ...

  7. atitit.MIZIAN 陕北方言 特有词汇 大词典 attilax 整理 a--g v1 q31.xlsx

    atitit.MIZIAN 陕北方言 特有词汇 大词典 attilax 整理 a--g v1 q31.xlsx 1  Mizian陕北方言 english英语 spain西班牙语 cantonese粤 ...

  8. Android JNI和NDK学习(02)--静态方式实现JNI(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3095013.html JNI包括两种实现方法:静态和动态.两种方法的区别如下 ...

  9. Unix 环境高级编程

    UNIX 环境高级编程 本书描述了UNIX系统的程序设计接口--系统调用接口和标准C库提供的很多函数. 与大多数操作系统一样,Unix为程序员运行提供了大量的服务--打开文件,读文件,启动一个新程序, ...

  10. 通信协议之广播---recvfrom 放回客户端的ip地址第一次全为0.0.0.0

    遇到一个很恶心的问题. while(1) { recvfrom(sockfd, readbuff, UDP_CMD_BUFF_LENGTH - 1, 0, (struct sockaddr *)&am ...