MySQL主从复制
-
复制的功用:
- 数据分布
- 负载均衡读
- 备份
- 高可用和故障切换
- MySQL升级测试
-
MySQL复制架构:
- Master/Slave 一主一从
- Master/Master 主主
- 环状复制
- 一主多从
- 从服务器还可以再有从服务器(级联复制)
- 一从多主:适用于多个不同数据库
主从复制原理:
主节点产生数据的更改,会将更改写入到二进制文件中,从节点启动一个线程,将自己伪装成MySQL的客户端,通过mysql协议向mysql服务器端读取二进制日志中的事件,服务器端会从二进制日志中的指定位置,将事件发送给从节点,从节点先将这些事件保存到本地的中继日志中,并将事件在本地回放
主从复制线程:
-
主节点:
- DUMP Thread:用来接收从节点的响应请求,并检查本地的二进制日志中有新的事件,然后将新的事件响应给从节点
-
从节点:
- I/O Thread:向master请求二进制日志事件,并保存到中继日志中
- SQL Thread:从中继日志中读取日志事件,在本地重放
和复制功能相关的文件:
- master.info:用于保存slave连接至master时的相关的信息,例如账号、密码、服务器地址等
- relay-log.info:保存在当前slave节点上已复制的当前二进制日志和本地replay log日志的对应关系
主从复制特点:
- 异步复制
- 主从数据不一致比较常见
复制需要考虑二进制日志事件的记录格式:
- STATEMENT(5.0之前):基于语句记录
- ROW(5.1之后,推荐):基于行记录
- MIXED:混合模式
复制架构总应该注意的问题:
-
1.限制从服务器为只读
- 在从服务器上设置read_only=on
注:此限制对super用户无效
- 阻止所有用户, 包括主服务器复制的更新
mysql> FLUSH TABLES WITH READ LOCK;
- 在从服务器上设置read_only=on
-
2.reset slave
- 在从服务器清除master.info,relay-log.info,relay log,开始新的relay log
注意:要先stop slave
- RESET SLAVE ALL 清除所有从服务器上设置的主服务器同步信息如:PORT, HOST, USER和 PASSWORD 等
- 在从服务器清除master.info,relay-log.info,relay log,开始新的relay log
-
3、sql_slave_skip_counter = N 从服务器忽略几个主服务器的复制事件,global变量
-
4.如何保证主从复制的事务安全
-
在master节点启用参数:
sync_binlog=1 每次写后立即同步二进制日志到磁盘,性能差
-
如果用到的为InnoDB存储引擎:
innodb_flush_log_at_trx_commit=1 每次事务提交立即同步日志写磁盘
innodb_support_xa=ON 默认值,分布式事务MariaDB10.3.0废除
sync_master_info=# #次事件后master.info同步到磁盘 -
在slave节点启用服务器选项:
skip_slave_start=ON 不自动启动slave
-
在slave节点启用参数:
sync_relay_log=# #次写后同步relay log到磁盘
sync_relay_log_info=# #次事务后同步relay-log.info到磁盘
-
配置主从复制:
- 主节点配置: 172.22.45.131
- 启用二进制日志
[mysqld]
log_bin=/path/to/file
例:log_bin=mariadb-bin #那么会在默认的/var/lib/mysql/下生产mariadb-bin.000001 ...等日志文件
2. 为当前节点设置一个全局的唯一ID
[mysqld]
server_id=131 #默认为1 主节点和从节点的id不能相同
log-basename=master #可选项,设置datadir中日志名称,确保不依赖主机名
3. 创建有复制权限的用户账号:
grant replication slave on *.* to 'repluser'@'host' identified by 'password';
- 从节点配置:
- 启动中继日志:
[mysqld]
server_id=132 #为当前节点设置一个全局惟的ID号
read_only=ON #设置数据库只读
relay_log=relay-log #relay log的文件路径,默认值为hostname-relay-bin
relay_log_index=relay-log.index #默认值为hostname-relay-bin.index
- 使用有复制权限的用户账号连接至主服务其,并启动复制线程
change master to master_host='host',master_user='repluser',master_password='password',master_log_file='mariadb-bin.000001',master_log_pos=245;
#master_log_file='mariadb-bin.000001' master_log_pos=245:指定从主服务器的哪个二进制日志的哪个事件开始复制
- 启动从节点线程:
start slave [IO_THREAD|SQL_THREAD];
- 查看同步状态:
show slave status\G;
如果主节点已经运行了一段时间,且有大量数据时,如何配置并启动slave节点:
- 通过备份恢复数据至从服务器
- 复制起始位置为本分时,二进制日志文件及其post
配置主主复制:互为主从
容易产生的问题:数据不一致;因此慎用
考虑要点:自动增长id
配置一个节点使用奇数id
auto_increment_increment=2 增长幅度
auto_increment_offset=1 开始点
另一个节点使用偶数id
auto_increment_offset=2
auto_increment_increment=2
- 主服务器1配置:172.22.45.131
- 启用二进制日志
[mysqld]
log_bin=/path/to/file
auto_increment_offset=1
auto_increment_increment=2
- 为当前节点设置一个全局的唯一ID
[mysqld]
server_id=131
log-basename=master
- 创建有复制权限的用户账号:
grant replication slave on *.* to 'repluser'@'host' identified by 'password';
- 主服务器2配置:172.22.45.132
- 启用二进制日志
[mysqld]
log_bin=/path/to/file
auto_increment_offset=2
auto_increment_increment=2
- 为当前节点设置一个全局的唯一ID
[mysqld]
server_id=132
log-basename=master
- 使用有复制权限的用户账号连接至主服务其,并启动复制线程:
change master to master_host='172.22.45.131',master_user='repluser',master_password='admin123',master_log_file='mariadb-bin.000001',master_log_pos=245;
- 启动线程
start slave;
- 主服务器1:
- 使用有复制权限的用户账号连接至主服务其,并启动复制线程:
change master to master_host='172.22.45.132',master_user='repluser',master_password='admin123',master_log_file='mariadb-bin.000001',master_log_pos=245;
- 启动线程
start slave;
配置级联复制:
- 主服务器: 172.22.45.131
- 启用二进制日志
[mysqld]
log_bin=/path/to/file
- 为当前节点设置一个全局的唯一ID
[mysqld]
server_id=131
log-basename=master
- 创建有复制权限的用户账号:
grant replication slave on *.* to 'repluser'@'host' identified by 'password';
- 从节点配置: 172.22.45.132
- 启动中继日志:
[mysqld]
server_id=132
read_only=ON
skip_name_resolve=on
log_bin
log_slave_updates #会把从主节点中继日志复制的内容,也写到自己的二进制日志中
relay_log=relay-log
relay_log_index=relay-log.index
- 使用有复制权限的用户账号连接至主服务其,并启动复制线程
change master to master_host='172.22.45.131',master_user='repluser',master_password='password',master_log_file='mariadb-bin.000001',master_log_pos=245;
- 启动从节点线程:
start slave [IO_THREAD|SQL_THREAD];
- 查看同步状态:
show slave status\G;
- 最后从节点配置:172.22.45.133
- 启动中继日志:
[mysqld]
server_id=133
read_only=ON
relay_log=relay-log
relay_log_index=relay-log.index
- 使用有复制权限的用户账号连接至主服务其,并启动复制线程
change master to master_host='172.22.45.132',master_user='repluser',master_password='password',master_log_file='mariadb-bin.000001',master_log_pos=245;
- 启动从节点线程:
start slave [IO_THREAD|SQL_THREAD];
- 查看同步状态:
show slave status\G;
半同步复制:
默认情况下,mysql的复制功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失
半同步复制能够实现,客户端在主服务器修改数据后,主服务器将日志发送给从服务器,在指定的时间内,如果从服务器完成复制,则返回成功给客户端,如果在指定时间内没有完成复制,也会返回成功给客户端
-
半同步复制的实现:
- 依赖于semisync_master.so和semisync_slave.so插件
- 查看数据库当前加载的插件:
show plugins;
- 安装插件
INSTALL PLUGIN name SONAME ‘plugin_name’;
name:为在show plugins;中看到的名字 - 启用插件:
set global name_enabled=1
-
主服务器配置:
- 安装插件:
install plugin rpl_semi_sync_master soname ''semisync_master.so';
- 启用插件:
set global rpl_semi_sync_master_enabled=1
- 设置超时时长:
set global rpl_semi_sync_master_timeout=1000; 超时时长为1s
- 查看相关的变量:
SHOW GLOBAL VARIABLES LIKE '%semi%';
- 查看状态:
SHOW GLOBAL STATUS LIKE '%semi%';
-
从服务器配置:
- 安装插件:
install plugin rpl_semi_sync_slave soname ''semisync_slave.so';
2. 启用插件:
set global rpl_semi_sync_slave_enabled=1