【二进制日志的结构】
二进制日志事件又称为binlog事件存储在一系列的binlog文件中,另外还有一个binlog的索引文件,用来追踪已有的binlog文件。
当前服务器正在写入的binlog文件称为活动文件。
索引文件的每一行都包含一个二进制日志的binlog文件名;
【binlog事件结构】
每个binlog事件由4部分组成:
通用头(Common header)
提交头(Post header)
事件体(Event body)
校验和(Checksum)
http://www.linuxidc.com/Linux/2017-03/142322.htm
【Format_description事件、Rotate事件】
这两个日志事件的长度是固定的
【事件校验】
MySQL5.6引入复制事件校验和。这写入事件的时候添加一个校验和;然后在读取这些事件的时候,计算这个校验和,并与之前的校验和进行比较,如果不匹配则在slave应用该事件之前终止执行;
可以使用相关命令进行设置;
【将语句写入日志】
写入数据操作语言(DML):》MySQL在写二进制日志的同时获取事务级锁,写完之后释放;
写入数据定义语言(DDL)语句:》对于一个数据库的表结构而言,只有一个锁来保护这些数据结构,所以数据库对象的创建、更新和销毁都可能带来性能问题。
写入查询:》需要将一些隐式的信息显示化的存储在日志中,以确保数据的一致性;
【二进制日志过滤器】
binlog-do-db:只是过滤特定数据库
binlog-ignore-db:忽略某个数据库而复制其他所有数据库
可以重复使用。
需要在my.cnf文件中进行设置:
[mysqld]
binlog-ignore-db=one_db
binlog-ignore-db=two_db
如果存在binlog-do-db机会忽略掉binlog-ignore-db语句
【记录日志的时候需要特别处理的结构:存储程序,即触发器、事件和存储例程】
存储例程stored routines是存储过程和存储函数的总称;
可以分为两种类型:
(1)定义、销毁或者更改存储程序的语句;
(2)调用它们的语句;
【LOAD_FILE函数】
LOAD_FILE可以读取某个文件,并将其使用在表达式中,但是这就要求slave上必须要有这个文件,因为复制过程并不会传递这个文件。而LOAD_DATA_INFILE中的文件将会被传递。所以可以使用LOAD_DATA_INFILE语句巧妙地重写带有LOAD_FILE函数的语句,或者自定义一个变量保存该文件的内容;
【将事务写入日志】
为了保证以事务为单位写二进制日志,服务器需要把语句分到不同的线程执行。提交事务的时候,服务器把所有这些语句一次性的全部写入二进制日志。为此,服务器为每个线程保留了一个事务缓存。将语句存放在事务缓存中,当事务提交的时候,将事务缓存的内容复制到二进制日志,然后清空;
【使用XA进行分布式事务处理】
MySQL5.0可以通过X/Open DTP(分布式事务处理)模型即XA,协调处理涉及不同资源的事务。
XA由一个事务管理器(transaction manager)和一组资源管理器(resource manager)组成,资源管理器将全局事务以原子单位提交,事务管理器则负责协调这些资源管理器。每个事务有一个唯一的XID,供事务管理器和资源管理器使用。在MySQL服务器内部,事务管理器通常由二进制日志使用,而资源管理器由存储引擎使用。每个存储引擎都需要为提交做准备。只要有一个存储引擎返回的消息是否定的,就无法提交这个事务,提交被终止,所有引擎执行事务回滚;
普通事务是以带有COMMIT的普通Query事件结束,而XA事务以一个包含XID的Xid事件结束;
【二进制日志的组提交】
多个独立的事务可以按组的形式,一起写入磁盘,这就是组提交(group commit)。写磁盘的时间取决于磁盘头移动到正确磁盘位置的时间,与写入多少数据量无关,所以这样能够极大地提高性能;
【基于行的复制】
基于语句复制无法正确处理的问题:
(1)如果UPDATE、DELETE或者INSERT语句包含LIMIT从句,那么语句执行的时候倘若数据库崩溃,则可能导致错误;
(2)如果非事务型语句执行期间出错,无法保证master和slave上数据变化一致;
(3)如果语句含有UDF函数调用,则无法保证slave上的值和master上的相同;
(4)如果语句含有任何不确定的函数,例如USER、CURRENT_USER、CONNECTION_ID等,可能会导致master和slave上的结果不一致;
(5)如果语句同时更新两个含有autoincrement字段的表,则无法保证正确性。因为只有最后插入的那个ID会被复制到slave上然后同时应用到两张表中去,而对于master来说,每张表的插入ID是不同的;
基于行的复制(row-based replication):复制插入表中的真实数据
使用基于行复制还是基于语句复制:
(1)如果语句要更新大量的行,则基于语句的复制更快(如果语句的优化和执行计划很复杂,也可能基于行的复制更快);
(2)如果master和slave上的数据不一致,执行语句的结果也会不同。这就需要基于行的复制来避免这种情况的发生;
【启用基于行的复制】
配置MySQL的配置文件:配置基于行的复制参数
binlog-format=ROW
【使用混合模式】
混合模式复制的原理:正常情况下使用基于语句的复制,而对不安全的语句则切换到基于行的复制。
例如以下情况混合模式会切换到基于行的复制:
(1)该语句调用了UUID函数、用户自定义函数、CURRENT_USER或者USER函数、LOAD_FILE函数
(2)一个语句同时更新了两个或者两个以上含有AUTO_INCREMENT列的表;
(3)语句中使用了服务器变量;
(4)存储引擎不允许使用基于语句的复制,例如:MySQL Cluster引擎;
【二进制日志管理】
因为二进制日志由多个文件组成,有必要将它们分隔成适当的组,构成一个binlog文件序列。为了操作安全,向二进制日志添加一些特殊的事件(轮换事件);
【binlog文件轮换】
因为操作系统对文件的大小有限制,,根据上下文不同,切换到新文件的过程称为二进制日志轮换,或者binlog文件轮换;
主要有4种行为导致轮换:
(1)服务器停止
(2)binlog文件大小达到最大限制(可以通过binlog-cache-size来控制binlog文件的大小)
(3)二进制日志被显示刷新:
FLUSH LOGS命令将所有日志写入磁盘,然后创建一个新文件继续写二进制日志。当PITR管理恢复镜像的时候,是很有用的。从一个打开的binlog文件可能会读到预料之外的结果,因此建议在试图使用binlog文件执行恢复前,强制进行显示刷新;
(4)服务器上发生故障
【事故】
(1)Stop:服务器正常停止;不会影响复制;
(2)Incident:当slave重放二进制日志时,如果遇到Incident事件,就会因为错误而停止。如果在MySQL集群重载时候发现Incident事件,表明需要重新同步集群,很可能还需要找到那些binlog文件中丢失的事件;
【清除binlog文件】
设置expire-logs-days选项:服务器可以自动清除binlog文件(可在my.cnf文件中配置)
手动清除命令:PURGE BINARY LOGS BEFORE datetime
该命令清除给定时间前的所有文件。
PURGE BINARY LOGS TO ‘filename’
该命令清除给定文件前的所有文件。即,在SHOW MASTER LOGS 命令显示的所有文件中,filename前的文件都会被清除,从而filename变成第一个binlog文件;
【mysqlbinlog实用工具】
http://blog.chinaunix.net/uid-22570852-id-4992233.html
对管理员十分有用的一个工具是客户端程序mysqlbinlog。这是一个小程序,可以审查binlog文件以及中继日志文件的内容。除了在本地读取binlog文件,mysqlbinlog同样可以从其他服务器上远程读取binlog文件;
读取远程文件:read-from-remote-server读取远程binlog文件,其参数包括需要连接服务器的主机和用户、可选的端口号以及密码
从远程服务器上读取binlog文件的时候,只需要给出binlog文件的名字,而不需要给出它的全路径;
【二进制日志的选项和变量】
有一组选项和变量用于对二进制日志进行多方面的配置;
有几个选项用于存储诸如binlog文件名和索引文件名这样的属性。大多数选项可以同时作为服务器变量处理。
【基于行的复制参数】
配置基于行的复制需要以下参数:
binlog-format
binlog-max-row-event-size
指定何时开始下一个包含行事件。由于事件在处理的时候被完全读入内存,该参数粗略的控制那些包含行的事件的大小,保证处理行的时候不会消耗过多的内存;
binlog-rows-query-log-events
该选项使服务器在行事件之前向二进制添加一个信息事件。这个信息事件包含产生这些行的原始查询;