MySQL的复制是通过将一台主(master)服务器的数据复制到其他主机(slaves) 上。从服务器可以有很多。而复制的原理跟MySQL的二进制日志是分不开关系的。
主服务器将更新写入二进制日志系统,并维护一个索引跟踪日志的循环,这些日志发送到从服务器上更新。从服务器通知主服务器,并从主服务器的日志上读取最后一次的成功更新的位置。
当使用事务的存储引擎InnoDB时,所有未提交的事务会记录到一个缓存中,等待事务提交时,直接将缓冲中的二进制日志写入二进制日志文件,而该缓冲的大小由binlog_cache_size决定,默认大小为32KB,此外,binlog_cache_size是基于回话的,也就是,当一个线程开始一个事务时,mysql会自动分配一个大小为binlog_cache_size的缓存,因此该值得设置需要相当小心,可以通过show global status 查看binlog_cache_use、binlog_cache_disk_use的状态.
复制的过程
整体来说,复制分为3个步骤。
(1). master 将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events)。
(2).slave 将master的二进制日志(binary log)拷贝到它的中继日志中(relay log)。
(3).slave重做中继日志中的事件,将日志中记录的SQL语句在本机上执行一遍。
MySQL的大体复制过程如上,下来详细介绍一下复制的过程。
步骤一:master记录二进制日志,在每个事务更新数据完成之前,master在二进制日志中记录这些改变,MySQL将事务串行写入二进制日志,在事件写入二进制日志完成后,会通知存储引擎提交事务。
步骤二:slave将master的二进制日志拷贝过来放到自己的中继日志中,首先,slave开始一个工作线程---I/O线程。I/O线程在master上打开一个普通的连接,开始接受二进制日志。I/O线程会将这些事件写入到中继日志中,如果已经跟上了master 的更新速度则睡眠等待产生新的事件。
步骤三:SQL从线程会处理最后一步,SQL线程会从中继日志中读取事件,并更新自己的数据。中继日志一般来说会保存到OS的缓存中,所以中继日志很小。
此外,在master中会有一个工作线程,复制过程中有一个限制---复制在slave上串行化,也就是master上并行更新操作不在slave上并行操作。所以导致slave上的同步数据很慢,慢于master服务器。
因为和MySQL主从复制有关的主要是二进制日志(bin-log)和中继日志(relay log),所以主要介绍的是这两种日志,其他的会简单的提一下。
MySQL主要有五种日志:
错误日志(error-log):
查询日志(general query log):
慢查询日志(log-slow-queries):
二进制日志(binary-log):
中继日志(relay-log):
MariaDB [(none)]> show variables like 'log_%';
+---------------------------------+--------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------------------------+--------------------------------------------------------------------------------------------------------------+
| log_bin | OFF |
| log_bin_trust_function_creators | OFF |
| log_error | /var/log/mariadb/mariadb.log |
| log_output | FILE |
| log_queries_not_using_indexes | OFF |
| log_slave_updates | OFF |
| log_slow_filter | admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk |
| log_slow_queries | OFF |
| log_slow_rate_limit | 1 |
| log_slow_verbosity | |
| log_warnings | 1 |
+---------------------------------+--------------------------------------------------------------------------------------------------------------+
11 rows in set (0.12 sec)
查询日志:记录着服务器接收到的每一个查询或是命令。无论查询是否有语法错误。同样一般不会开启的。
慢查询日志:其中记录了每个语句的执行时间,消耗时间,执行的用户,连接主机等信息。
二进制日志(重点):
二进制日志(-log-bin)的主要功能是 恢复和复制 。
binlog有一些其他的参数
max_binlog_size 设置的最大存储上线,当日志达到上限时,mysql会重新创建一个日志开始记录,不过偶尔也会超过上限。比如即将到达上限时来一个比较大的事务。为了保证事务的安全性,mysql会将同一个事务写进同一个binlog里面。
binlog-do-db = db_name明确告诉mysql。只记录指定的数据库。
binlog-ignore-db = db_name :忽略对某个数据库的日志记录。
mysql> show variables like '%binlog%';
+-----------------------------------------+----------------------+
| Variable_name | Value |
+-----------------------------------------+----------------------+
| binlog_cache_size | 32768 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_format | MIXED |
| binlog_stmt_cache_size | 32768 |
| innodb_locks_unsafe_for_binlog | OFF |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| sync_binlog | 0 |
+-----------------------------------------+----------------------+
9 rows in set (0.00 sec)
log_bin_index = /var/log/mysql/mysql-bin.log.index --二进制日志索引的名称
查看二进制日志。
[root@realser2 data]# mysqlbinlog mysql-bin.000007
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#170301 12:31:56 server id 1 end_log_pos 107 Start: binlog v 4, server v 5.5.12-log created 170301 12:31:56 at startup
可以使用 purgebinary logs 来清除binary logs。
binlog_format 参数很重要:
参数值 :(1)。STATEMENT格式和之前的mysql一样。二进制文件是记录日志的SQL语句
(2)。ROW格式下,记录的是行的更改情况。(建议)
(3)。MIXED格式。
中继日志(重点):
中继日志也是二进制文件,但是用来给slave库恢复的。