一、mysql复制
1、mysql复制
MySQL复制是指从一个MySQL主实例服务器(master)将数据复制到另一台或多台MySQL从从实例服务器(slaves)的过程。MySQL复制的数据粒度可以是主实例上所有的数据库,也可以是指定的一个或多个数据库,也可以是一个数据库里的指定的表。默认复制操作是异步进行的,salves服务器不需要持续的保持连接接受master服务器的数据。
2、mysql复制的作用
(1)扩展能力:通过复制功能可以将MySQL的性能压力分担到一个或多个slave实例上。
(2)数据库备份:由于从实例是同步主实例的数据,所以可以将备份作业部署到从库
(3)数据分析和报表:一些数据分析和报表的实现可以在从实例执行,以减少对主库的性能影响
(4)容灾能力:异地同步,提升容灾能力
3、mysql复制的方法
(1)传统方式:基于主库的bin-log将日志事件和事件位置复制到从库,从库再加以应用来达到主从同步的目的
(2)Gtid方式:global transaction identifiers是基于事务来复制数据,因此也就不依赖日志文件,同时又能更好的保证主从库数据一致性
4、复制的类型
(1)异步复制:一个主库,一个或多个从库,数据异步同步到从库
(2)同步复制:在MySQL Cluster中特有的复制方式
(3)半同步复制:在异步复制的基础上,确保任何一个主库上的事务在提交之前至少有一个从库已经收到该事务并日志记录下来
(4)延迟复制:在异步复制的基础上,人为设定主库和从库的数据同步延迟时间,即保证数据延迟至少是这个参数
5、mysql复制的模式
(1)基于语句的复制(statement based replication):基于主库将SQL语句写入到bin log中完成复制
优势:1)技术比较成熟,应用广泛
2)使用语句复制节省空间
3)可以用来做审计功能(该二进制文件中包含了所有的语句)
缺点:某些特定的修改语句在复制时会有问题(一些存储过程和函数)
(2)基于行数据的复制(row based replication):基于主库将每一个行数据变化的信息作为事件写入到bin log中完成日志。
优势:1)所有的数据库修改都可以被复制,是一种安全的方式
2)由于是行复制,所以某些语句在主库和从库上执行需要较少的lock
缺点:1)DML语句涉及到多行的修改时,导致bin log会很大
2)不能直接查看在备库中执行的SQL语句
(3)混合复制(mixed based replication):上述两者的结合。默认情况下优先使用基于语句的复制,只有当部分语句如果基于语句复制不安全的情况下才会自动切换为基于行数据的复制
6、主从复制时的线程
(1)binlog dump thread:在主库创建,用来在从库连接过来时发送bin log的内容
(2)slave io thread:在备库创建,用来连接主库并请求发送新的bin log内容。该线程读取主库的bin log dump线程发送的更新内容并将此内容复制到本地的relay log中
(3)Slave sql thread:在备库创建,读取slave io线程在本地relay log中的内容并在本地执行内容中的事件
二、mysql基于bin-log日志的复制
1、mysql复制的原理
在主库的二进制日志里记录了对数据库的变更,从库从主库那里获取日志,然后在从库中重放这部分日志,从而实现数据的同步
2、复制步骤
(1)主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。
(2)从库复制主库的二进制日志事件到本地的中继日志(relay log)。
(3)从库重放中继日志。
3、复制配置
(1)配置复制前主备工作
在复制前需准备好主库和从库并在主库创建一个专门用来做复制的数据库用户,并确保这个用户有复制的权限。
主机地址 | 功能 | 执行复制的用户 | Mysql版本 |
192.168.16.151 | 主库 | repl | 5.7.23 |
192.168.16.152 | 从库 |
| 5.7.23 |
# 在主库上创建用于复制的用户
mysql> CREATE USER 'repl'@'192.168.16.%' IDENTIFIED BY 'replication';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.16.%';
(2)配置主库
在复制前主库需要开启bin-log,并且指定一个唯一的server-id,配置完成后重启数据库;同时也要确保配置文件中skip-networking参数为非开启状态,否则会导致主从库不能通信而复制失败。
在同一个复制组下的所有实例的server_id都必须是唯一的,而且取值必须是正整数,取值范围是1~(232)−1。
# 配置主库的server-id及开启binglog,配置完成后需要重启mysql
[mysqld]
log-bin=mysql-bin
server-id=1
# 重启后查看log_bin的状态
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------------+
| Variable_name | Value |
+---------------------------------+----------------------------------+
| log_bin | ON |
| log_bin_basename | /data/mysql/data/mysql-bin |
| log_bin_index | /data/mysql/data/mysql-bin.index |
(3)获取主库的日志信息
为了确保建立的备库能从正确的bin log位置开启复制,要首先获取主库的bin log信息,包括当前的日志文件名和日志文件内的位置;在操作前需要锁定主库,直到获取的big log位置前的日志传到从库为止。
# 锁定所有的表,防止写入
mysql> FLUSH TABLES WITH READ LOCK;
# 获取当前日志信息
mysql> SHOW MASTER STATUS\G
*************************** 1. row ***************************
File: mysql-bin.000001
Position: 154
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.00 sec)
(4)将主库当前的数据同步到从库
复制建立前同步时可通过两种方式实现:一种是用mysqldump命令实现(innodb存储引擎推荐的方式);另一种是把主库临时关闭,将数据文件从主库拷贝到从库,这种方式效率更高(省去了dump/import过程中insert语句执行导致的更新index的行为)。
# 将主库上的数据导出并传到从库
~]# mysqldump --all-databases --master-data -u root -p > dbdump.db
~]# scp dbdump.db root@192.168.16.152:/data/mysql/data
# 在主库上释放锁
mysql> unlock tables;
(5)配置从库并在从库上导入数据
从库上也需要配置唯一server-id,bin log属性可以可以更具自己的需要可打开卡不打开。
# 配置从库的server-id并重启重库
[mysqld]
server-id=2
从库配置完成后需要将从主库到处的数据在从库导入。
# 在从库上导入主库导出的数据
]# mysql -uroot -p </data/mysql/data/dbdump.db
(6)在从库上配置主库信息并导入数据
在上面配置完成后就可以在从库上配置主库的相关信息,并通过”start slave”命令启动复制功能,在从库上需要配置主库的一下信息:
MASTER_HOST=’master_host_name’:主库的主机名
MASTER_PORT=port_number:主库的端口号
MASTER_USER=’replication_user_name’:复制的数据库用户名
MASTER_PASSWORD=’replication_password’:复制的用户密码
MASTER_LOG_FILE=’recorded_log_file_name’:主库的日志文件名 MASTER_LOG_POS=recorded_log_position:主库的日志文件位置
# 登录从库配置与主库相关的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.16.151',
-> MASTER_PORT=3306,
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replication',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.41 sec)
# 启动主从复制
mysql> start slave;
Query OK, 0 rows affected (0.05 sec)
(7)查看复制是否正常
# 在从库上查看复制是否正常
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.16.151
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 474
... .. .
(8)一主多从环境的配置
在创建从库时可以同时创建多个从库,如果当前的主从环境启动后还想添加主从,则可以直接使用先前使用的备份文件及主库的状态建立主从复制 。
# 修改第三台mysql数据库的server-id并重启
[mysqld]
server-id=3
# 将主库的备份文件复制过来并导入
~]# scp root@192.168.16.151:/data/dbdump2.db ./
~]# mysql -uroot -p <dbdump2.db
# 登录当前从库配置与主库相关的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.16.151',
-> MASTER_PORT=3306,
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replication',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=154;
# 启动复制
mysql> start slave;
# 查看复制状态
mysql> show slave status\G
如果再增加从库时,为了减轻主库的压力,也可设置让复制从当前建立好的从库中去复制数据。
4、复制模式的配置
(1)基于语句的复制的配置
基于语句的复制在主库的配置文件中添加以下内容:
# 基于语句复制的配置
binlog-format=statement
(2)基于行复制的配置
基于行的复制在主库的配置文件中添加以下内容:
# 基于行的二进制文件的复制
binlog-format=row
# 查看当前数据库的复制方式
mysql> show variables like '%format%';
+---------------------------+-------------------+
| Variable_name | Value |
+---------------------------+-------------------+
| binlog_format | ROW |
三、mysql基于GTID的复制
1、GTID复制
GTID复制是完全基于事务的复制,即每个在主库上执行的事务都会被分配一个唯一的全局ID并记录和应用在从库上,这种复制方式简化了建立slave和master之间切换的工作,因为其完全不需要找当前执行的bin log和log中的位置完成切换。
一个GTID是master上执行的任何commit事务所分配的全局唯一ID标示,其由两部分组成:GTID = source_id:transaction_id;Source_id代表主库的server_uuid,transaction_id代表事务按顺序提交的ID。
2、GTID的复制过程
(1)当一个事务在主库提交时,该事务就被赋予了一个GTID,并记录在主库的binary log
(2)主库的binary log会被传输到从库的relay log中,从库读取此GTID并生成gtid_next系统参数
(3)从库验证此GTID并没有在自己的binary log中使用,则应用此事务在从库上
3、配置主库及从库,将之前的基于bin-log复制改为GTID复制
5.6版本中的GTID复制模式,slave必须开启bin-log和log_slave_updates参数,否则启动就报错,因为需要在binlog找到同步复制的信息(UUID:事务号);5.7版本中, gtid_executed系统表记录同步复制的信息(UUID:事务号),这样就不用开启log_slave_updates参数,减少了从库的压力。
# 设置主库及从库为只读模式
mysql> SET @@global.read_only = ON;
# 关闭主库及从库
[root@localhost ~]# mysqladmin -uroot -p shutdown
# 在主库及从库配置中添加以下配置文件并启动主从两个实例
gtid-mode=on
#确保只有对gtid复制机制安全的语句才会被log
enforce-gtid-consistency=on
skip-slave-start=1
# 在从库上从新配置主从复制关系并启动slave进程
mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.16.151',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='replication',
-> MASTER_AUTO_POSITION=1;
mysql> start slave;
# 关闭主库及从库的read only模式
mysql> SET @@global.read_only = OFF;
# 在从库上查看主从复制的状态
mysql> show slave status\G
4、使用GTID复制的制约条件
(1)当master和slave的表使用的存储引擎不一样时,会导致GTID复制功能不正常
(2)GTID复制不支持create table … select语句
(3)create/drop temporary table语句在GTID复制环境中不能放在事务中执行,只能单独执行,并且autocommit要开启
(4)sql_slave_skip_counter语句是不支持的,如果想要跳过事务,可以使用gtid_executed变量
四、mysql复制时使用的参数及查看复制状态
1、mysql复制时的参数
(1)server_id:是必须设置在master和每个slave上的唯一标识ID,其取值范围是1~4294967295之间,且同一个复制组之内不能重复
(2)server_uuid:server_uuid会在GTID复制中使用。当MySQL启动之后,会首先到数据文件目录下的auto.cnf中寻找是否有指定的server_uuid,如果没有找到,则自己生成一个server_uuid并保存到这个文件中
(3)log_slave_updates:该参数用来控制是否将收到的主库的更新数据的语句也记录在slave自己的bin log中
(4)relay-log:该参数用来指定relay-log文件的基础名称,默认的名称为host_name-relay-bin.xxxx
(5)replicate-do-db:该参数用来指定需要复制的数据库,有多个数据库需要复制,则这个参数要使用多次。
(6)replicate-ignore-db:该参数决定了忽略指定数据库的复制
(7)replicate-do-table=db_name.tbl_name:通过该参数告知slave的SQL thread仅复制指定表上的数据。如果有多个表,则该参数要使用多次
(8)replicate-ignore-table=db_name.tbl_name:通过该参数告知slave的SQL thread将指定表上的数据过滤掉
(9)replicate-wild-do-table=db_name.tbl_name:通过该参数告知SQL的SQL thread仅复制符合匹配的表,可以使用_和%作为通配符
(10)replicate-wild-ignore-table=db_name.tbl_name:通过该参数告知SQL的SQL thread过滤掉符合匹配的表。
(11)slave-parallel-workers: 该参数决定了slave上启动多个SQL thread线程来并行应用数据的。默认值是0代表不允许并行,取值范围可以是0~1024
(12)skip-slave-start :该参数决定了在MySQL启动时是否先不启动slave线程,即暂停复制
(13)slave-skip-errors=[err_code1,err_code2,...|all|ddl_exist_errors]:该参数决定了当slave的SQL thread执行过程中碰到何种错误时可以忽略并继续接下来的数据复制
(14)slave-parallel-type=type :该参数决定了当启动了并行之后,采用什么粒度的并行方式。默认值database表示按照不同的数据库执行并行,LOGICAL_CLOCK则表示按照在binlog中的一组提交的事务作为并行粒度
(15)sql_slave_skip_counter代表在非GTID复制环境下,通过设置此参数来跳过多少个复制事件。该参数会在下次执行start slave命令时生效
(16)log-bin[=base_name] :该参数表示是否开启binary log
(17)binlog-do-db=db_name: 该参数决定了哪些库下的修改会被记录到bin log中。
(18)binlog-ignore-db=db_name:该参数决定了在bin log中忽略的数据库
(19)binlog_format:该参数决定了bin log中记录的格式,值有statement,row,mixed,分别代表基于SQL语句的复制,基于行复制和基于混合复制。
2、复制状态的查看
在主库可以通过执行show processlist命令查看主库的bin log日志生成进程;在从库上可以通过执行”show slave status”来检查复制是否正常工作,主要的参数说明如下:
Slave_IO_State:代表当前slave的状态 S
lave_IO_Running:代表负责读取主库bin log的IO线程的运行状态
Slave_SQL_Running:代表负责执行备库relay log的SQL线程的运行状态
Last_IO_Error, Last_SQL_Error: 分别代表最后一次IO线程和SQL线程所发生的错误,没有则为空。
Seconds_Behind_Master:代表备库的SQL线程比主库的bin log晚多少秒
Master_Log_file, Read_Master_Log_Pos:表示IO线程在主库bin log中的坐标位置 Relay_Master_Log_File, Exec_Master_Log_Pos:表示SQL线程在主库bin log中的坐标位置
Relay_Log_File, Relay_Log_Pos:表示SQL线程在备库relay log中的坐标位置
五、延迟复制与半同步复制
1、延迟复制
延迟复制是指定从库对主库的延迟至少是指定的这个间隔时间,默认是0秒。可以通过” CHANGE MASTER TO MASTER_DELAY = N”命令来指定,其原理是从库收到主库的bin log之后,不是立即执行,而是等待指定的秒数之后再执行。
(1)配置延迟复制
# 在从库上配置延迟复制,延迟90秒
mysql> stop slave;
mysql> CHANGE MASTER TO MASTER_DELAY = 60;
mysql> start slave;
# 查看复制状态
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.16.151
…
SQL_Delay: 60
(2)延迟复制使用场景
1)确保在主库上被错误修改的数据能及时找回
2)测试在从库IO集中在恢复bin log过程中对应用程序的访问影响
3)保留一份若干天前的数据库状态,和当前状态可以做对比
2、半同步复制
(1)半同步复制
当主库执行一个更新操作事务时,提交操作会被阻止直到至少有一个半同步的复制slave确认已经接收到本次更新操作,主库的提交操作才会继续;半同步复制的slave发送确认消息只会在本次更新操作记录已经记录到本地的relay log之后,如果没有任何slave发送确认消息而导致超时时,半同步复制会转换成异步复制
(2)配置半同步复制
mysql5.7版本通过扩展的方式支持了半同步复制, 在建立半同步前需要分别在主库和从库安装一个插件。
主库的配置:
# 在主库上安装插件并配置主库
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
# 开启主库半同步复制
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
# 设置主库半同步复制超时时间,超过此时间则转为异步复制
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 5;
从库的配置:
# 在备库上安装插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
# 在备库开启半同步复制
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
# 重启备库slave进程
mysql> STOP SLAVE IO_THREAD;
mysql> START SLAVE IO_THREAD;
3、半同步复制状态查看
半同步复制状态的查看可通过” SHOW STATUS LIKE 'Rpl_semi_sync%';”命令查看。
# 在主库上查看半同步状态
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 9090 |
| Rpl_semi_sync_master_tx_wait_time | 9090 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+--------------------------------------------+-------+
# 从库上查看半同步状态
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
主要参数说明:
Rpl_semi_sync_master_clients:检查半同步的slave个数
Rpl_semi_sync_master_status:ON表示主库的半同步功能开启并且运行正常,OFF表示主库的半同步功能关闭或者半同步复制 已经变成了异步复制
Rpl_semi_sync_master_no_tx:表示有多少提交没有收到slave的确认消息
Rpl_semi_sync_master_yes_tx:表示有多少个提交收到了slave的确认消息
Rpl_semi_sync_slave_status:ON表示备库上slave功能开启并且运行正常,OFF表示功能为开启或者运行异常