第2章 MySQL复制原理
基于复制的常见案例:通过热备份来避免灾难(hot standby)、产生报表、调试和审计。
配置master
确保该服务器有一个活动的二进制日志(binary log)和唯一的服务器ID
1、修改my.cnf,添加如下配置选项,并重启mysql以生效。
log-bin = /data/mysql/binlog/mysql-bin #二进制日志产生的所有文件的基本名。如不赋值,默认为hostname-bin,建议手动赋值。不要中途改名,否则会很混乱。
log-bin-index = /data/mysql/binlog/mysql-bin.index #二进制索引文件的文件名,该文件将保存所有binlog文件的列表,建议手动赋值。否则,改变主机名并重启服务器后,将找不到索引文件,从而认为索引文件不存在,导致二进制日志为空。
server-id = 1
2、创建复制用户(非必须,但最好还是将复制slave用户与其他用户区分开)
master> CREATE USER repl_user@10.0.0.12;
master> GRANT REPLICATION SLAVE ON *.* TO repl_user@10.0.0.12 IDENTIFIED BY 'root'; # IDENTIFIED BY '这里定义密码'
master> FLUSH PRIVILEGES;
配置slave
和master一样,需要修改my.cnf,并重启mysql以生效。
server-id = 2
relay-log-index = slave-relay-bin.index #中继日志索引文件。如不赋值,默认为hostname-relay-bin,建议手动赋值。
relay-log = slave-relay-bin #中继日志。建议手动赋值。
连接master和slave
有2步是必须的:CHANGE MASTER TO(将slave指向master,让它知道从哪里进行复制)和START SLAVE(启动复制)
slave> SLAVE STOP;
slave> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.11',
-> MASTER_USER='repl_user',
-> MASTER_PASSWORD='root';
#-> MASTER_PORT=3306; #非必须
slave> START SLAVE;
这些参数代表:
MASTER_HOST: 主机的IP或者名称
MASTER_USER: 授予REPLICATION SLAVE权限的用户,在这个例子中就是“repl_user”
MASTER_PASSWORD: 分配给“repl_user”的密码,在这个例子中就是“root”
MASTER_PORT: 指定端口号,默认3306
二进制日志简介
语句执行结束时,将在二进制日志的末尾写入一条记录,同时通知语句解析器语句已经执行完毕。通常只有即将执行完毕的语句才会被写入二进制日志,但是在一些特殊情况下其他信息也会被写入,以对语句进行添加和替换。
二进制日志的目的是记录数据库中表的改变,然后用于复制和PITR,另外少数审计情况下也会用到。
注意二进制日志只包括数据库的改动,所以对那些不改变数据的语句则不会写入二进制日志。
binlog_format:Mixed,Statement,Row
In MySQL 5.6, the default format is STATEMENT. Exception: For MySQL Cluster NDB 7.3, the default is MIXED; 参看http://dev.mysql.com/doc/refman/5.6/en/replication-options-binary-log.html#sysvar_binlog_format
Statement,基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。一旦发现没法精确复制时, 会自动选着基于行的复制。
Row,基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
Mixed,混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。
二进制日志的结构和内容
二进制日志并不是一个单独的文件,而是由一系列易于管理的(例如在不影响新日志的情况下移除旧的日志)文件组成的。二进制日志包括一组存储实际内容的二进制日志文件和一个二进制日志索引文件,而二进制索引文件包含所有使用的二进制日志文件的文件名,它用来跟踪存在的二进制日志文件。
每个二进制日志文件都以格式描述事件开始,以日志轮换事件结束。一个事件是构成二进制日志的基本单位,只能存储在一个文件中,永远不能跨两个文件。
SHOW BINLOG EVENTS IN 'master-bin.000002'\G #如果没指定IN 'xx bin',SHOW BINLOG EVENTS语句只显示第一个二进制日志文件的内容
SHOW MASTER STATUS\G #查看当前正在写入的是哪个二进制文件
RESET MASTER #删除所有二进制日志文件并清空二进制日志索引。警告:确保没有slave连接到该master。
RESET SLAVE #删除slave复制所用的所有文件,重新开始。警告:先执行STOP SLAVE,确保slave没有活动的复制。
使用Python管理复制
待学习
建立新slave
如果没有说明复制从哪里开始,slave将从头开始读取master上的二进制日志,显然不是个好方法。
CHANGE MASTER TO有2个参数,可指定master开始发送时间的binlog位置,而不是从头开始:
MASTER_LOG_FILE: 之前通过SHOW MASTER STATUS;看到的binlog文件名
MASTER_LOG_POS: 之前通过SHOW MASTER STATUS;看到的position
slave> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.11',
-> MASTER_USER='repl_user',
-> MASTER_PASSWORD='root',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=107;
克隆master
克隆master首先要创建master的备份,由于master正在运行,而且缓存中有很多表,所以需要刷新(flush)所有表并锁定数据库,放置在检查binlog位置之前数据库发生改变。使用FLUSH TABLES WITH READ LOCK命令来完成。
master> FLUSH TABLES WITH READ LOCK; #在主机上执行,刷新所有的表并阻断写操作
master> SHOW MASTER STATUS; #在主机上读取当前的二进制日志名称和偏差的值
File“列显示了日志的名称,”Position“列显示了日志在文件中的偏差量。写下这些值,因为后面你设置从机的时候你会用到它们。
$ mysqldump -u root -p abc > /root/abc_20131111.sql #备份abc数据库
扩展阅读:
备份所有数据库 $ mysqldump --all-databases > all.sql
--all-databases或--databases,mysqldump会为每一个数据库写入CREATE DATABASE和USE。以确保当备份文件被再次载入的时候,如果数据库不存在则创建数据库,然后设置为当前数据库(USE DATABASES),当INSERT的时候数据库的内容均会加载到同一个数据库中。
如果想要备份文件载入时强制删除数据库,可以使用--add-drop-database。这样mysqldump会在CREATE DATABASE前写入DROP DATABASE。
master> UNLOCK TABLES; #记得解锁
克隆slave
与克隆master基本相同,区别在于如何找到binlog位置。
original-slave> STOP SLAVE;
original-slave> FLUSH TABLES WITH READ LOCK;
original-slave> SHOW SLAVE STATUS; #记录Relay_Master_Log_File和Exec_Master_Log_Pos字段的值
创建了备份然后在新slave上恢复,将复制配置为从这个位置开始,然后启动新的slave:
new-slave> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.11',new-slave> START SLAVE;
-> MASTER_USER='repl_user',
-> MASTER_PASSWORD='root',
-> MASTER_LOG_FILE='$Relay_Master_Log_File ',
-> MASTER_LOG_POS=$Exec_Master_Log_Pos;
创建备份常见的方式是调用FLUSH TABLES WITH READ LOCK, 然后归档数据库文件。
注意:在InnoDB中使用FLUSH TABLES WITH READ LOCK是不安全的!!!
FLUSH TABLES WITH READ LOCK会锁定表,这样就不会产生任何新的事务,但后台任然有一些活动在继续进行。