项目需要做Es和数据库的同步,而手动在代码中进行数据同步又是Es的一些不必要的数据同步操作和业务逻辑耦合,所以使用的了读取mysql的binlog日志的方式进行同步Es的数据。
问题1:根据binlog同步数据的时候会不会出现业务逻辑利用事务操作数据的时候,当事务还没有提交的时候,是否能够读到binlog,也就是binlog的写入时机(是事务提交的之前写,还是事务提交后写)。问题2:如果事务提交之前写入binlog,那么事务提交之前,事务回滚,那么binlog又会出现什么情况?
首先我们做一下实验(前提是必须要打开binlog),SQL初始化语句
create table user(
id bigint not null auto_increment
primary key,
name varchar(64) null,
status tinyint(1) null
);
insert into user (name,status)values ('张三',1);
set autocommit = 0;
2.1:事务提交对binlog的影响
我们先确定一下MySQL执行更新SQL语句之后,执行commit命令前后,binlog会有什么变化。
然后我们先使用 show master status 看一下binlog的位置
然后我们执行一下更新语句
update user set status = status + 1;再次使用 show master status 查看发现并没有Position并没有变,执行commit命令之后,发现Position由141169变为了141506,说明从库只有在主库提交之后才能读到主库写入的binlog日志。
2.2:事务回滚对binlog的影响
我们再确定一下MySQL执行更新SQL语句之后,执行rollback命令前后,binlog会有什么变化。
然后我们先使用 show master status 看一下binlog的位置
然后我们执行一下更新语句
update user set status = status + 1;再次使用 show master status 查看发现并没有Position并没有变,执行rollback命令之后,发现Position仍然没有变化,说明事务回滚之后binlog并不会写入磁盘。
难道binlog是在事务提交之后才写入磁盘的嘛?那redo log 又是什么时候写入磁盘的呢?有上面的问题又引发一系列的问题,带着这些问题,我们来进行mysql日志的深入学习。
3:MySQL更新数据的执行流程首先我们要先了解一下当我们做一条数据的更新操作的时候,数据库的底层到底是如何执行的?
MySQL更新数据执行流程:
1:判断数据页是否在内存中,若为否,则从磁盘读取数据到内存中,返回数据行2:若是数据页在内存中,则直接返回数据行
3:执行数据更新操作
4:数据写入内存,同时redolog写入到内存
5:执行commit操作(此commit是SQL命令操作,而不是数据的commit状态)
6:执行commit命令之后,则进行两段提交操作。
6.1:写入内存中的redolog到磁盘中,此时redolog处于prepare状态
6.2:写入binlog到磁盘
6.3:提交事务,此时事务处于commit状态
7:结束。
注:以上操作为参数innodb_flush_log_at_trx_commit 为1和sync_binlog为1的时候。
对应MySQL的更新语句执行流程图,如图1-1。
redo log:被称之为重做日志,是在数据库发生意外时,进行数据恢复,redo log会备份是事务执行过程中的修改数据。
binlog: 被称为归档日志,是一个二进制格式的文件,用于记录用户对数据库更新的SQL语句信息,格式分为(statement、row、mixed)