主从复制的原理
- 从节点启动一个专用的IO线程,把自己扮演成一个mysql客户端,通过mysql协议,向mysql服务端请求读取对方二进制中的事件
- 服务器端启动一个dump thread线程检查自己二进制日志中的事件并和对方请求发来的二进制日志的position进行比较,然后将从position开始的二进制日志发送给从节点
- 从服务器收到之后将事件保存至中继日志中,并记录读取到的position
- 从节点再次启动一个sql_thread线程,从中继日志中读取二进制日志,然后执行二进制中的事件
主从复制架构实现
主节点配置步骤:
- 启动二进制日志
- 为当前节点设置一个全局唯一的ID号
- 创建有复制权限的用户账号:REPLACATION SLAVE, REPLACATION CLIENT
从节点配置步骤:
- 启动中继日志
- 为当前节点设置一个全局唯一的ID号
- 使用有复制权限的用户账号连接至主服务器,并启动复制线程
配置过程(192.168.2.69为主节点 192.168.2.234为从节点)
#主节点:#主要是加入log_bin和server-idcat /etc/my.cnf [mysqld] log-bin = mysql-bin server-id = 1 innodb_file_per_table = 1 skip_name_resolve = 1 #创建复制权限的账号 mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.2.%' IDENTIFIED BY 'template';mysql> FLUSH PRIVILEGES;
#从节点cat /etc/my.cnf [mysqld] innodb_file_per_table = 1 relay_log = relay-log server_id = 2 skip_name_resolve = 1 innodb_file_per_table = 1#在主节点上使用SHOW MASTER STATUS查看二进制日志binlog的位置mysql> CHANGE MASTER TO -> MASTER_HOST='192.168.2.69', -> MASTER_USER='repluser', -> MASTER_PASSWORD='template', -> MASTER_PORT=3306, -> MASTER_LOG_FILE='mysql-bin.000002', -> MASTER_LOG_POS=120, -> MASTER_CONNECT_RETRY=10; #启动slavemysql> start slave;#至此主从已经配置完成----------------------------------------------------------------------------------------------#可以使用SHOW SLAVE STATUS\G查看slave状态mysql> show slave status\G
复制架构中注意的问题:
限制从服务器为只读
在从服务器上设置read_only = on 此限制对拥有super权限的用户均无效,如果想阻止所有用户写操作,可以使用:mysql> FLUSH TABLES WITH READ LOCK;
如何保证主从复制的事务安全?
在master节点启用参数:
sync_binlog = on
sync_master_info = 1
如果用到的为InnoDB存储引擎:
innodb_flush_logs_trx_commit = on
innodb_support_xa = on
在slave节点:
skip_slave_start = on
sync_relay_log = 1
sync_relay_log_info = 1
如果主节点已经运行了一端时间,且有大量数据时,如何配置并启动slave节点?
通过备份恢复数据至从服务器
复制起始位置为备份时,二进制日志文件及其POS
主主复制架构实现
要点:两个节点,每个都要启动二进制日志和中继日志,并且互为主从
主主复制的问题:
- 数据不一致:因此慎用
- 自动增长ID:配置一个节点使用奇数ID(auto_increment_offset = 1 auto_increment_increment = 2),另一个节点使用偶数ID(auto_increment_offset = 2 auto_increment_increment = 2)
配置步骤
- 各节点使用一个唯一的server_id
- 都启用binary log和relay log
- 创建拥有复制权限的用户账号
- 均把对方指定为主节点,并启动复制线程
#两节点配置文件#第一个节点: [mysqld] socket = /tmp/mysql.sock log-bin = mysql-bin relay_log = relay-log server-id = 2 innodb_file_per_table = 1 skip_name_resolve = 1 slow_query_log = 1 #第二个节点 [mysqld] socket = /tmp/mysql.sock log-bin = mysql-bin relay_log = relay-log server-id = 1 innodb_file_per_table = 1 skip_name_resolve = 1 slow_query_log = 1 #在两个节点上都创建复制权限的账号mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.2.%' IDENTIFIED BY 'template';mysql> FLUSH PRIVILEGES;#使用SHOW MASTER STATUS;查看对方服务器的binlog的日志mysql> show master status;+------------------+----------+--------------+------------------+-------------------+| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |+------------------+----------+--------------+------------------+-------------------+| mysql-bin.000003 | 833 | | | |+------------------+----------+--------------+------------------+-------------------+#然后每个节点上都执行change to master操作mysql> CHANGE MASTER TO -> MASTER_HOST='192.168.2.234', -> MASTER_USER='repluser', -> MASTER_PASSWORD='template', -> MASTER_PORT=3306, -> MASTER_LOG_FILE='mysql-bin.000003', -> MASTER_LOG_POS=833, -> MASTER_CONNECT_RETRY=10; mysql> START SLAVE;#查看slave状态mysql> SHOW SLAVE STATUS;
半同步复制架构实现
半同步复制是谷歌为mysql5.5以后的版本提供的一个插件,所谓半同步是可以有多个从节点,但只保证其中一个从节点收到并在本地存储下来数据(如果一个节点有n个从节点,它只需要等待一个从节点存储完数据并返回以后,才向客户端返回)
要实现半同步复制需要有两个插件:semisync_master.so semisync_slave.so(如果是源码包安装的话在 /usr/local/mysql/lib/plugin/下)
配置步骤
主节点配置过程:
#主节点配置文件 [mysqld] socket = /tmp/mysql.sock log-bin = mysql-bin server-id = 1 innodb_file_per_table = 1 skip_name_resolve = 1 slow_query_log = 1##授权复制用户 GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.2.%' IDENTIFIED BY 'template';#装载semisync插件mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; #启用插件 mysql> SET GLOBAL rpl_semi_sync_master_enabled=1;
从节点配置过程:
#从节点配置文件 [mysqld] socket = /tmp/mysql.sock server-id = 2 relay_log = relay-log innodb_file_per_table = 1 skip_name_resolve = 1 slow_query_log = 1 #使用SHOW MASTER STATUS;查看主服务器的binlog的日志状态#从节点执行mysql> CHANGE MASTER TO -> MASTER_HOST='192.168.2.69', -> MASTER_USER='repluser', -> MASTER_PASSWORD='template', -> MASTER_PORT=3306, -> MASTER_LOG_FILE='mysql-bin.000002', -> MASTER_LOG_POS=120, -> MASTER_CONNECT_RETRY=10;#装载semisync插件mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';查看半同步节点个数#mysql> SHOW GLOBAL STATUS LIKE '%semi%';查看插件是否加载#mysql> SHOW GLOBAL STATUS LIKE '%semi%';#启动插件mysql> set global rpl_semi_sync_slave_enabled=1 #启动slavemysql> START SLAVE;
复制过滤器
让从节点仅复制指定的数据库,或指定数据库的指定表
有两种实现方式:
主服务仅向二进制日志中记录与特定数据库(特定表)相关的事件
binlog_do_db=(数据库白名单)
binlog_ignore_db=(数据库黑名单)
上面两个参数不要同时使用
问题:时间还原无法实现:不建议使用
从服务器SQL_THREAD在replay中继日志中的事件时,仅读取与特定数据库(特定表)相关的事件并应用于本地
问题:会造成网络及磁盘IO浪费
replicate_do_db=
replicate_ignore_db=
replicate_do_table=
replicate_ignore_table=
replicate_wild_ignore_table=
基于SSL的复制
前提:支持ssl
- master端要配置证书和私钥,并且创建一个要求必须使用SSL连接的复制账号
- slave端使用CHANGE MASTER TO 命令时指明ssl相关选项
mysql> help change master toName: 'CHANGE MASTER TO'Description:Syntax:CHANGE MASTER TO option [, option] ...option: MASTER_BIND = 'interface_name' | MASTER_HOST = 'host_name' | MASTER_USER = 'user_name' | MASTER_PASSWORD = 'password' | MASTER_PORT = port_num | MASTER_CONNECT_RETRY = interval | MASTER_RETRY_COUNT = count | MASTER_DELAY = interval | MASTER_HEARTBEAT_PERIOD = interval | MASTER_LOG_FILE = 'master_log_name' | MASTER_LOG_POS = master_log_pos | MASTER_AUTO_POSITION = {0|1} | RELAY_LOG_FILE = 'relay_log_name' | RELAY_LOG_POS = relay_log_pos | MASTER_SSL = {0|1} | MASTER_SSL_CA = 'ca_file_name' | MASTER_SSL_CAPATH = 'ca_directory_name' | MASTER_SSL_CERT = 'cert_file_name' | MASTER_SSL_CRL = 'crl_file_name' | MASTER_SSL_CRLPATH = 'crl_directory_name' | MASTER_SSL_KEY = 'key_file_name' | MASTER_SSL_CIPHER = 'cipher_list' | MASTER_SSL_VERIFY_SERVER_CERT = {0|1} | IGNORE_SERVER_IDS = (server_id_list) ##查看是否支持ssl mysql> show global variables like '%ssl%';
跟复制功能相关的文件
master.info:用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等
relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地relay log日志的对应关系
复制的监控和维护
清理二进制日志:
PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';复制监控:
SHOW MASTER STATUS;
SHOW BINLOG EVENTS;
SHOW BINARY LOGS;
SHOW SLAVE STATUS;
SHOW PROCESSLIST;
从服务器是否落后于master
SHOW SLAVE STATUS;
Seconds_Behind_Master: 0
如何确定主从节点数据是否一致
percona-tools
数据不一致如何修复
重新复制