什么是二进制日志(binlog)
binlog是记录所有数据库表构造变更(例如CREATE、ALTER TABLE…)以及表数据批改(INSERT、UPDATE、DELETE…)的二进制日志。
binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据自身并没有批改,但你能够通过查问通用日志来查看MySQL执行过的所有语句。
二进制日志包含两类文件:二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查问语句)语句事件。
什么是事务日志
innodb事务日志包含redo log和undo log。
undo log指事务开始之前, 在操作任何数据之前,首先将需操作的数据备份到一个中央
redo log指事务中操作的任何数据,将最新的数据备份到一个中央
事务日志的目标:实例或者介质失败,事务日志文件就能派上用场。
1.redo log不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo 中。具体 的落盘策略能够进行配置 。避免在产生故障的工夫点,尚有脏页未写入磁盘,在重启mysql服务的时候,依据redo log进行重做,从而达到事务的未入磁盘数据进行长久化这一个性。RedoLog是为了实现事务的持久性而呈现的产物
2.undo log用来回滚行记录到某个版本。事务未提交之前,Undo保留了未提交之前的版本数据,Undo中的数据可作为数据旧版本快照供其余并发事务进行快照读。是为了实现事务的原子性而呈现的产物,在Mysql innodb存储引擎中用来实现多版本并发管制
Redolog常识补充
指定Redo log 记录在{datadir}/ib_logfile1&ib_logfile2 可通过innodb_log_group_home_dir 配置指定 目录存储
一旦事务胜利提交且数据长久化落盘之后,此时Redo log中的对应事务数据记录就失去了意义,所 以Redo log的写入是日志文件循环写入的
指定Redo log日志文件组中的数量 innodb_log_files_in_group 默认为2
指定Redo log每一个日志文件最大存储量innodb_log_file_size 默认48
指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默认16Redo buffer 长久化Redo log的策略, Innodb_flush_log_at_trx_commit:
取值 0 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能失落一秒的事务数据]
取值 1 默认值,每次事务提交执行Redo buffer --> Redo log OS cache -->flush cache to dis[最平安,性能最差的形式]
取值 2 每次事务提交执行Redo buffer --> Redo log OS cache 再每一秒执行 ->flush cache tdisk操作
快照读和以后读
快照读:SQL读取的数据是快照版本,也就是历史版本,一般的SELECT就是快照读 innodb快照读,数据的读取将由 cache(本来数据) + undo(事务批改过的数据) 两局部组成
以后读:SQL读取的数据是最新版本。通过锁机制来保障读取的数据无奈通过其余事务进行批改 UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE都是 以后读
Undo + Redo事务的简化过程
假如有A、B两个数据,值别离为1,2,开始一个事务,事务的操作内容为:把1批改为3,2批改为4,那么理论的记录如下(简化):
- A.事务开始.
- B.记录A=1到undo log.
- C.批改A=3.
- D.记录A=3到redo log.
- E.记录B=2到undo log.
- F.批改B=4.
- G.记录B=4到redo log.
- H.将redo log写入磁盘。
- I.事务提交
二进制日志处理事务和非事务性语句的区别
在事务性语句(update)执行过程中,服务器将会进行额定的解决,在服务器执行时多个事务是并行执行的,为了把他们的记录在一起,须要引入事务日志的概念。在事务实现被提交的时候一起刷新到二进制日志。对于非事务性语句(insert,delete)的解决。遵循以下3条规定:
1)如果非事务性语句被标记为事务性,那么将被写入重做日志。
2)如果没有标记为事务性语句,而且重做日志中没有,那么间接写入二进制日志。
3)如果没有标记为事务性的,然而重做日志中有,那么写入重做日志。
留神如果在一个事务中有非事务性语句,那么将会利用规定2,优先将该影响非事务表语句间接写入二进制日志。
XA的概念
XA(分布式事务)标准次要定义了(全局)事务管理器(TM: Transaction Manager)和(部分)资源管理器(RM: Resource Manager)之间的接口。XA为了实现分布式事务,将事务的提交分成了两个阶段:也就是2PC (tow phase commit),XA协定就是通过将事务的提交分为两个阶段来实现分布式事务。
两阶段
1)prepare 阶段
事务管理器向所有波及到的数据库服务器收回prepare"筹备提交"申请,数据库收到申请后执行数据批改和日志记录等解决,解决实现后只是把事务的状态改成"能够提交",而后把后果返回给事务管理器。即:为prepare阶段,TM向RM收回prepare指令,RM进行操作,而后返回胜利与否的信息给TM。
2)commit 阶段
事务管理器收到回应后进入第二阶段,如果在第一阶段内有任何一个数据库的操作产生了谬误,或者事务管理器收不到某个数据库的回应,则认为事务失败,回撤所有数据库的事务。数据库服务器收不到第二阶段的确认提交申请,也会把"能够提交"的事务回撤。如果第一阶段中所有数据库都提交胜利,那么事务管理器向数据库服务器收回"确认提交"申请,数据库服务器把事务的"能够提交"状态改为"提交实现"状态,而后返回应答。即:为事务提交或者回滚阶段,如果TM收到所有RM的胜利音讯,则TM向RM收回提交指令;不然则收回回滚指令。
- 内部与外部XA
MySQL中的XA实现分为:内部XA和外部XA。前者是指咱们通常意义上的分布式事务实现;后者是指单台MySQL服务器中,Server层作为TM(事务协调者,通常由binlog模块担当),而服务器中的多个数据库实例作为RM,而进行的一种分布式事务,也就是MySQL跨库事务;也就是一个事务波及到同一个MySQL服务器中的两个innodb数据库(目前仿佛只有innodb反对XA)。外部XA也能够用来保障redo和binlog的一致性问题。
事务日志与二进制日志的一致性问题
咱们MySQL为了兼容其它非事务引擎的复制,在server层面引入了 binlog, 它能够记录所有引擎中的批改操作,因此能够对所有的引擎应用复制性能; 然而这种状况会导致redo log与binlog的一致性问题;MySQL通过外部XA机制解决这种一致性的问题。
第一阶段:InnoDB prepare, write/sync redo log;binlog不作任何操作;
第二阶段:蕴含两步,1> write/sync Binlog; 2> InnoDB commit (commit in memory);
当然在5.6之后引入了组提交的概念,能够在IO性能上进行一些晋升,但总体的执行程序不会扭转。
当第二阶段的第1步执行实现之后,binlog曾经写入,MySQL会认为事务曾经提交并长久化了(在这一步binlog就曾经ready并且能够发送给订阅者了)。在这个时刻,就算网站监控数据库产生了解体,那么重启MySQL之后仍然能正确复原该事务。在这一步之前蕴含这一步任何操作的失败都会引起事务的rollback。
第二阶段的第2步大部分都是内存操作(留神这里的InnoDB commit不是事务的commit),比方开释锁,开释mvcc相干的read view等等。MySQL认为这一步不会产生任何谬误,一旦产生了谬误那就是数据库的解体,MySQL本身无奈解决。这个阶段没有任何导致事务rollback的逻辑。在程序运行层面,只有这一步实现之后,事务导致变更能力通过API或者客户端查问体现进去。
上面的一张图,阐明了MySQL在何时会将binlog发送给订阅者。
MySQL会在binlog落盘之后会立刻将新增的binlog发送给订阅者以尽可能的升高主从提早
如何开启mysql的binlog
`vi /etc/my.cnf`
log-bin=mysql-bin #增加这一行就ok
binlog-format=ROW #抉择row模式
server_id=1 #配置mysql replaction须要定义,不能和canal的slaveId反复
Binlog常见格局
业内目前举荐应用的是row模式,准确性高,尽管说文件大,然而当初有SSD和万兆光纤网络,这些磁盘IO和网络IO都是能够承受的。
在innodb里其实又能够分为两局部,一部分在缓存中,一部分在磁盘上。这里业内有一个词叫做刷盘,就是指将缓存中的日志刷到磁盘上。跟刷盘无关的参数有两个个:sync_binlog和binlog_cache_size。这两个参数作用如下
binlog_cache_size: 二进制日志缓存局部的大小,默认值32k
sync_binlog=[N]: 示意每多少个事务写入缓冲,刷一次盘,默认值为0
留神两点:
(1)binlog_cache_size设过大,会造成内存节约。binlog_cache_size设置过小,会频繁将缓冲日志写入临时文件。
(2)sync_binlog=0:示意刷新binlog工夫点由操作系统本身来决定,操作系统本身会每隔一段时间就会刷新缓存数据到磁盘,这个性能最好。sync_binlog=1,代表每次事务提交时就会刷新binlog到磁盘,对性能有肯定的影响。sync_binlog=N,代表每N个事务提交会进行一次binlog刷新。
另外,这里存在一个一致性问题,sync_binlog=N,数据库在操作系统宕机的时候,可能数据并没有同步到磁盘,于是再次重启数据库,会带来数据失落问题。
mysql的binlog是多文件存储,定位一个LogEvent须要通过binlog filename + binlog position,进行定位
table_map event & write_rows event
这两个event是在binlog_format=row的时候应用,设置binlog_format=row,而后创立一个测试表
CREATE TABLE trow
( i
int(11) NOT NULL, c
varchar(10) DEFAULT NULL, PRIMARY KEY (i
) ) ENGINE=InnoDB DEFAULT CHARSET=latin1`
执行语句INSERT INTO trow VALUES(1, NULL), (2, 'a'),这个语句会产生一个query event,一个table_map event、一个write_rows event以及一个xid event。
罕用的开源框架原理
1.原理
- 框架模仿mysql slave的交互协定,假装本人为mysql slave,向mysql master发送dump协定
- mysql master收到dump申请,开始推送binary log给slave(也就是canal)
- 框架解析binary log对象(原始为byte流)
2.框架
2.1、mysql-binlog-connector-java
目前开源的 CDC (change data capture)工具,如 Zendesk maxwell、Redhat debezium、LinkedIn Databus 等都底层依赖 mysql-binlog-connector-java
或者其前身 open-replicator
不须要独立部署
稳定性不是很好,工夫久了会呈现connetion lost的状况
2.2、canal
须要独立部署canal server服务
canal 已在阿里云推出商业化版本 数据传输服务DTS, 开明即用,免去部署保护的低廉应用老本。DTS针对阿里云RDS、DRDS等产品进行了适配,解决了Binlog日志回收,主备切换、VPC网络切换等场景下的订阅高可用问题。同时,针对RDS进行了针对性的性能优化。
HA机制设计
canal的ha分为两局部,canal server和canal client别离有对应的ha(主备模式)实现
- canal server: 为了缩小对mysql dump的申请,不同server上的instance要求同一时间只能有一个处于running,其余的处于standby状态.
- canal client: 为了保障有序性,一份instance同一时间只能由一个canal client进行get/ack/rollback操作,否则客户端接管无奈保障有序
canal 1.1.1版本之后, 默认反对将canal server接管到的binlog数据间接投递到MQ, 目前默认反对的MQ零碎有:
Kafka,RocketMQ。1.1.3版本下修复了投递MQ模式,canal server HA在切换后不失效