MySQL复制:
性能出现瓶颈时,两种扩展方式:
Scale Up,硬件升级
Scale Out,增加服务器
MySQL扩展:
对于Scale Out扩展方式,面临多台服务器的数据一致性问题。使用复制的方式解决。
复制:确保每个节点都有相同的数据集;
向外扩展方式、二进制日志;单向复制;主从结构;
复制的功用:
数据分布、负载均衡读、数据备份、高可用和故障切换、MySQL升级测试。
MySQL主从复制 :
从节点(Slave):
I/O Thread:从Master请求二进制日志事件,并保存于中继日志中;
SQL Thread:从中继日志中读取日志事件,在本地完成重放;
主节点(Master):
Dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events;

特定:
1、异步复制:主节点Dump进程发送events事件给从节点I/O进程,不需要等待从节点返回接收结果;
2、主从数据不一致比较常见:从节点数据落后于主节点;
3、从节点不需要二进制日志:
4、负载均衡,需要在应用层:需要理解请求SQL语句,实现读写分离,写SQL必须分发给主节点;r/w spliter,读写分离器,读写语句路由器;
复制架构:
M/S(主从架构),M/M(主主架构,双主架构),环状架构
一主多从:从服务器还可以再有从服务器;
一从多主?暂不支持;




二进制日志事件记录格式:
STATEMENT
ROW
MIXED
实践的模型:
主从、主主、半同步复制、复制过滤器
主从架构复制 :
主节点:
1)启动二进制日志;
mysqld
log_bin=mysql-bin
2)为当前节点设置一个全局唯一的ID号;
mysqld
server_id=#
3)创建有复制权限的用户账号:REPLICATION SLAVE,REPLICATION CLIENT
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'user'@'HOST' IDENTIFIED BY 'password';
从节点:
1)启动中继日志;
mysqld
relay_bin=relay-log
relay_log_index=relay-log.index
2)为当前节点设置一个全局唯一的ID号;
3)使用有复制权限的用户账号连接至主服务器,并启动复制线程;
mysql>CHANGE MASTER TO MASTER_HOST='host',MASTER_USER='USER',MASTER_PASSWORD='PASSWORD',MASTER_LOG_FILE='mysql-bin.xxxxxx',MASTER_LOG_POS=###;
mysql>START SLAVE [IO_THREAD | SQL_THREAD];
实操过程:
1)配置主配置文件/etc/my.cnf或/etc/my.cnf.d/目录下的server.cnf,配置为主节点:设置启动二进制日志,设置server ID:

启动mariadb:systemctl start mariadb
查看日志配置结果:

二进制日志启动

2)创建有复制权限的用户账号:

3)从节点配置:/etc/my.cnf

启动mariadb
4)从节点中启动复制,使用CHANGE MASTER TO
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_HEARTBEAT_PERIOD = interval
| MASTER_LOG_FILE = 'master_log_name'
| MASTER_LOG_POS = master_log_pos
| 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_KEY = 'key_file_name'
| MASTER_SSL_CIPHER = 'cipher_list'
| MASTER_SSL_VERIFY_SERVER_CERT = {0|1}
| IGNORE_SERVER_IDS = (server_id_list)
server_id_list:
server_id \[, server_id\] ...
示例:

在从节点执行CHANGE MASTER TO语句,配置好复制条件:

查看从节点状态:

执行START SLAVE,启动复制:START SLAVE语法
START SLAVE [thread_types]
START SLAVE [SQL_THREAD] UNTIL
MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
START SLAVE [SQL_THREAD] UNTIL
RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos
thread_types:
thread_type \[, thread_type\] ...
thread_type: IO_THREAD | SQL_THREAD


复制开始了。
5)测试复制
在主节点创建新数据库:

查看从节点:

数据已经复制到从节点了。
查看主节点状态:

二进制日志到588位置,再查看从节点:也到了588

如果主节点已经运行了一段时间,且有大量数据时,如何配置并启动slave节点?
1)通过备份恢复数据至从服务器;
2)复制起始位置为备份时,二进制日志文件及其POS;
复制架构中应该注意的问题:
1、限制从服务器为只读:

在从服务器上设置read_only=ON;此限制对拥有SUPER权限的用户均无效;
阻止所有用户:mysql>FLUSH TABLES WITH READ LOCK;
2、如何保证主从复制的事务安全:
在master节点启用参数:sync_binlog=ON
如果用到的是InnoDB存储引擎:建议开启如下配置
innodb_flush_logs_at_trx_commit=ON
innodb_support_xa=ON
在slave节点(从节点复制不要自动启动,手动开启比较安全): skip_slave_start=ON
从节点上的文件:/var/lib/mysql/下的info文件,包括master.info和relay-log.info

在重新启动从节点时,能够自动连接到主节点上,就是使用的这个文件的先关信息。
从节点中继日志的相关信息:

master节点配置项:sync_master_info,这个参数控制从属服务器更新 master info 的间隔

master_info_repository有两个值,分别是file和table,该参数决定了slave记录master的状态,如果参数是file,就会创建master.info文件,如果参数值是table,就在mysql中创建slave_master_info的表。sync_master_info参数决定slave刷新master的状态的方式。并且master_info_repository的参数不同,刷新方式也不同。
1)如果master_info_repository=file,sync_master_info=N,其中N>0,那么slave就会在每N个事件后,使用fdatasync()方式同步到master.info文件中。如果sync_master_info=N,其中N=0,那么MySQL就会把状态信息写入到OS Cache中,需要等待操作系统同步。
2)如果master_info_repository=table,sync_master_info=N,如果N>0,那么slave就会在,每N个事件后,更新mysql.slave_master_info表,如果N=0,那么mysql.slave_master_info表将永远不会更新。
slave节点:sync_relay_log 、sync_relay_log_info

sync_relay_log:这个参数和 Binlog 中的 sync_binlog 作用相同。当设置为 1 时,slave 的 I/O 线程每次接收到 master 发送过来的 Binlog 日志都要写入系统缓冲区,然后刷入 relay log 中继日志里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量 I/O。当设置为 0 时,并不是马上就刷入中继日志里,而是由操作系统决定何时来写入,虽然安全性降低了,但减少了大量的磁盘 I/O 操作。这个值默认是 0,可动态修改,建议采用默认值。
sync_relay_log_info:当设置为 1 时,slave 的 I/O 线程每次接收到 master 发送过来的 Binlog 日志都要写入系统缓冲区,然后刷入 relay-log.info 里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量 I/O。当设置为 0 时,并不是马上就刷入 relay-log.info 里,而是由操作系统决定何时来写入,虽然安全性降低了,但减少了大量的磁盘 I/O 操作。这个值默认是0,可动态修改,建议采用默认值。
主主架构复制 :互为主从,存在的问题
1)会有数据不一致情况;因此,慎用;
2)自动增长id:配置一个节点使用奇数,另一个使用偶数;
auto_increment_offset=1
auto_increment_incremnet=2
auto_increment_offset=2
auto_increment_incremnet=2
配置步骤:
(1)各节点使用一个唯一server_id;
(2)都启动binary log和relay log;
(3)创建拥有复制权限的用户账号;
(4)定义自动增长id字段的数值范围为奇偶;
(5)均把对方指定为主节点,并启动复制线程;
实操过程:
1)修改配置文件,两个节点都启动二进制日志和中继日志,配置server-d及自增id

2)启动mysql:systemctl start mariadb
查看日志状态:SHOW GLOBAL VARIABLES LIKE '%log%';
确保两个节点的二进制日志和中继日志都启动了
3)在每一个节点上创建具有复制权限的用户:

4)查看MASTER STATUS,记住两个节点的二进制日志及其位置:

5)互相指定对方为MASTER,配置复制条件:

启动复制:START SLAVE;
查看启动结果:SHOW SLAVE STATUS;
6)测试互相复制:节点128创建数据库repl,129节点复制,也有了repl库

节点129创建表tb01,插入数据,节点128也复制:



注意:自增id虽然不冲突,但是不连续了。
半同步复制模式 :
半同步复制模式下,主服务器(Master)至少等待一个从服务器(Slave)确认已经接收并写入数据后,才会向客户端确认操作成功。这意味着在主服务器上执行的事务只有在至少一个从服务器上也完成了写入,才能被认为已经提交。
半同步复制的优点:
数据一致性:提高了数据在主从服务器之间的最终一致性,减少了数据丢失的风险。
性能:相较于全同步复制,半同步复制的性能损失较小,因为它不需要等待所有从服务器确认。
可靠性:在大多数情况下,它比异步复制更可靠,因为它确保了数据在至少一个从服务器上已经安全写入。
相比异步复制,半同步复制牺牲了一定的性能,提升了主备之间数据的一致性(有一些情况还是会出现主备数据不一致)。
MySQL支持两种略有不同的半同步复制:AFTER_SYNC和AFTER_COMMIT(受rpl_semi_sync_master_wait_wait_point控制)。
开启半同步复制时,Master在返回之前会等待Slave的响应或超时。当Slave超时时,半同步复制退化成异步复制。这也是MySQL半同步复制存在的一个问题。
半同步复制模式是在插件方式下工作的,需要的插件:semisync_master和semisync_slave

1)配置两个节点为主从模式
master:

slave:

2)主节点上创建具有复制权限的用户:
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'repluser'@'192.168.61.%' IDENTIFIED BY 'replpass';
FLUSH PRIVILEGES;
3)从节点上配置复制条件,暂不启动SLAVE
查看主节点二进制日志状态:

从节点: CHANGE MASTER TO MASTER_HOST='192.168.61.128',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_LOG_FILE='master-bin.000003',MASTER_LOG_POS=498;
4)主从节点安装插件:
使用INSTALL PLUGIN语句:
INSTALL PLUGIN plugin_name SONAME 'shared_library_name'
plugin_name是插件的名字,shared_library_name是插件文件的名字。
主节点安装插件:INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

安装完毕查看插件:SHOW PLUGINS;

从节点安装插件:INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SHOW PLUGINS;
安装插件后,变量会多出几个:
主节点:

从节点:

全局状态变量:

启动半同步复制,主节点rpl_semi_sync_master_enabled设置为ON,从节点rpl_semi_sync_slave_enabled设置为ON


从节点上启动复制:START SLAVE;
主节点上再次查看状态变量:

半同步复制客户端有1个了。
5)主从半同步复制数据复制测试:
主节点创建数据库和表,插入数据,查看状态变量,查看从节点复制结果:


复制过滤器 :让从节点仅复制指定的数据库,或者指定数据库的指定表;
有两种实现方式:
(1)主服务器仅向二进制日志中记录与特定数据库(特定表)相关的事件;
问题:时间还原无法实现,因为二进制日志仅记录部分数据库事件:不建议使用;
binlog_do_db= #数据库白名单列表,指定复制哪些库
binlog_ignore_db= #数据库黑名单列表,指定不复制哪些库
(2)从服务器SQL_THREAD线程在replay中继日志中的事件时,仅读取与特定数据库(特定表)相关的事件并应用于本地;
问题:会造成网络及磁盘IO浪费;
replicate_do_db replicate_do_table replicate_wild_do_table 白名单
replicate_ignore_db replicate_ignore_table replicate_wild_ignore_table 黑名单
从服务器实现复制过滤器,只需在从服务器上设置相关变量:


测试复制:


主节点上创建testrpl数据库,没有复制到从节点,指定复制的rpldb,主节点上在其中的tb01表插入数据,在从节点数据被复制了。实现了过滤器复制。
基于SSL复制 :前提是支持SSL
(1)master配置证书和私钥,并且创建一个要求必须使用SSL连接的复制账号;
(2)slave端使用CHANGE MASTER TO时指明SSL相关选项;
跟复制功能相关的文件 :
master.info:用于保存slave连接至master时的相关信息,如账号,密码,服务器地址等
relay-log.info:保存在当前slave节点上已经复制的当前二进制日志和本地relay log日志的对应关系;
复制的监控和维护 :
(1)清理日志(在已经备份的前提下清理):PURGE
PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr }
Examples:
PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';
(2)复制监控:
SHOW MASTER STATUS;
SHOW BINLOG EVENTS;
SHOW BINARY LOGS;
SHOW SLAVE STATUS;
SHOW PROCESSLIST;
(3)从服务器是否落后于主服务器:
使用SHOW SLAVE STATUS;查看变量Seconds_Behind_Master:
(4)如何确定主从节点数据是否一致:
percona-tools工具
(5)数据不一致如何修复?
重新复制