主从复制 主从复制与相关概念介绍 mysql主从复制是mysql自带的一种容灾备份方案,通过逻辑的binlog日志复制到从节点,然后由本地线程读取地址的sql语句,应用到mysql数据库中
推荐架构 1主-1从、1主-2从、1主-1从-2从级联 其中级联模式可以缓解主的IO压力,主节点只需要将binlog复制给二级从节点即可
不推荐架构 1主-1主多主、2主-1从、1主-1主-1主环形
主从复制的步骤
1.客户端访问数据库-修改数据 2.数据改变时,master将提交的事务写入binlog 3.从库的IO线程请求主库binlog,主库dump线程将其发送给IO线程 4.IO线程对比binlog与中继日志,如果不同,IO线程将其同步给中继日志 5.从库sql线程读取中继日志,并将其解析为sql 6.根据解析的sql语句重新解析至从库数据库
主从复制的同步方式 异步复制 搭建简单,使用广泛,性能好,但异步有丢失数据的风险全同步复制 数据安全,一致性好,性能差传统半同步复制(5.5之后) 介于异步和全同步复制之间,折中了前两种无损复制(5.7之后) 增强版的半同步复制 数据零丢失,性能好
GTID特性 GTID全局事务ID,是对一个已提交事务的编号,全局唯一,在5.6.2之后开始支持 GTID和事务回记录到binlog中,用来标识事务,取代了传统的复制方法 每一个节点中,如果存在相同标识符,可以避免同一事务在同节点中出现多次,每个事务在集群中有了唯一性,数据安全性更高,故障切换更简单
GTID组成 Server_uuid mysql实例的全局唯一标识,位置$datadir/auto.cnfSequence_Number mysql内部事务的编号,一个mysql实例不会重复的序列号,也表示在该实例上已经提交事务的数量,并且跟随事务提交而递增
通过GTID可以知道事务最初在哪个实例上提交,方便故障排查和追踪
1 2 3 cat /usr/local/mysql/data/auto.cnf [auto] server-uuid=fcc43b8d-48e6-11ef-b6a8-bc241123c3a6
补充:数据库错误代码
错误代码
描述
1050
数据库已存在,创建表失败
1051
数据库不存在,删除表失败
1054
字段不存在,或程序文件和数据库有冲突
1060
字段重复
1064
SQL语法错误。
1094
Table ‘xxx’ is too large - 尝试操作的表太大,可能是因为超出了某些限制(如InnoDB表的最大大小)。
1146
Table ‘xxx’ doesn’t exist - 尝试访问的表不存在。
1053
Server shutdown in progress - 服务器宕机
1062
Duplicate entry ‘xxx’ for key ‘yyy’ - 主键冲突
主从复制搭建 1 2 3 4 5 环境 CentOS Linux release 7.9.2009 (Core) 192.168.10.125 mysql-1 192.168.10.126 mysql-2 192.168.10.127 mysql-3
主从复制相关参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 从节点可能要绑定主节点地址 bind-address=192.168.10.125 服务器id,主从不相同,建议使用ip+port的方式 server-id=253306 关闭 跳过主机名解析 skip_name_resolve=off 事务隔离级别使用读已提交 transaction-isolation=read-committed binlog参数: log_bin= log_bin_index= binlog_format=row binlog_rows_query_log_events=on 更详细的sql操作 sync_binlog=1 默认,每次提交事务,将binlog内容写入磁盘,保证binlog在服务器崩溃时不丢失 innodb_flush_log_at_trx_commit=1 默认,每次事务提交时将log buffer数据写入log file,并写入磁盘 log_bin_trust_function_creators=1 默认0,选择同步函数和存储过程 max_binlog_size=2024M 默认1024M,最大binlog大小 expire_logs_days=7 binlog最多保留多少天 binlog_cache_size=1M binlog缓存大小,默认32K,使其可以一次性提交更大的事务 innodb_support_xa=1 分布式事务,开启能确保事务写入binlog的顺序和事务time时间线一致,这样恢复时就会严格按照时间线进行恢复 从库的relay_log中继日志参数 relay_log=/usr/local/mysql/logs/relay.log relay_log_recover=1 打开中继日志恢复,支持自我修复(从主库重新获取) relay_log_info_repository=table 信息库方式,默认file,但sql线程写数据是写数据库操作,file是写文件操作,很难保持一致 master_info_repository=table 默认是file,IO线程根据收到的event,保存写的位置,设置为表table 同步方式参数 loose_rpl_semi_sync_master_enabled=1 mysql5.6主库启用半同步复制 loose_rpl_semi_sync_slave_enabled=1 mysql5.6从库启用半同步复制 loose_rpl_semi_sync_master_timeout=5000 超时五秒,切换为异步 rpl_semi_sync_master_wait_for_slave_count=1 至少收到1个slave发挥的ack rpl_semi_sync_master_wait_point=AFTER_SYNC mysql5.7开启无损同步 rpl_semi_sync_master_wait_point=AFTER_COMMIT mysql5.7开启半同步复制 GTID参数 log_slave_updates=1 主库开启,从库的binlog会记录主库的操作记录,从库不建议开 enforce_gtid_consistency=on ON如果发现事务或语句不支持gitd就会报错,WARN不支持则返回警告,OFF不检查 gtid_mode=on ON:产生gtid,从库只接受带gtid的事务 ON_PERMISSIVE:产生gtid,无论带不带gtid,从库都接收 OFF:不产生gtid,从库只接受不带gtid的事务 OFF_PERMISSIVE:不产生gtid,无论带不带gtid,从库都接收 gtid_executed_compression_period 控制表压缩率 gtid_next:automatic 获取下一个事务的方式,默认自动获取,当出现slave故障时需要跳过某事务时,可以通过set global gtid_next='xx'来手动指定 gtid_owned 表示正在执行的事务的gtid和线程id session_track_gtids 用于捕获和跟踪gitd,OFF关闭、OWN_GTID返回当前事务的gtid、ALL_GTIDS返回系统执行的所有gtid 复制过滤参数 主库: binlog-do-db 表示和A库相关的指令,会被写入二进制文件 binlog-ignore-db 表示忽略A库,除A库以外全都复制 从库: replicate_do_db replicate_ignore_db replicate_do_table replicate_ingnore_table replicate_wild_do_table 和第一条是对应,必须同时使用 replicate_wild_ingnore_table 和第二条是对应,必须同时使用 其他: binlog_gtid_simple_recovery=1 开启后,加快mysql重启时的恢复性能 并行参数(5.7开始),解决延时问题 slave-parallel-type=LOGICAL_LOCK 基于库的并行方式 slave-parallel-workers=4 4个并行复制的SQL回放线程 read_only=1 slave_preserve_commit_order=1 commit顺序保持一致 slave_skip_errors=ddl_exist_errors 跳过错误日志 默认off不跳过 all全部 ErroCode 特定错误参数,如1062 ddl_exist_errors DDL错误的参数
主从复制部署——(传统异步复制) 适合数据量少于50G
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 环境 192.168.10.125 mysql-1 192.168.10.126 mysql-2 创建一个主从复制用户 mysql -uroot -p create user 'repuser' @'%' identified by 'repuser123' ; grant replication client,replication slave on *.* to 'repuser' @'%' ; flush privileges; select user,host from mysql.user;主从的配置文件my.cnf基础添加 1.需要打开binlog log_bin=/usr/local/mysql/logs/bin.log log_bin_index=/usr/local/mysql/logs/binlog.index binlog_format=ROW binlog_rows_query_log_events=on 2.修改常规与安全性参数 bind-address=192.168.10.125/192.168.10.126 server-id=253306/263306 skip_name_resolve=on expire_logs_days=7 max_binlog_size=2024M binlog_cache_size=1M log_bin_trust_function_creators=1 innodb_support_xa=1 innodb_flush_log_at_trx_commit=1 sync_binlog=1 transaction-isolation=read-committed 3.在此基础上,从库额外添加参数 log_slave_updates=1 read_only=1 slave-parallel-type=LOGICAL_CLOCK slave-parallel-workers=4 master_info_repository=table relay_log_info_repository=table relay_log_recovery=1 slave_skip_errors=dll_exist_errors slave_preserve_commit_order=1 4.slave连接主库(部分信息需要在主库执行show master status查看) mysql -uroot -p stop slave; change master to master_host='192.168.10.125' , master_user='repuser' , master_password='repuser123' , master_log_file='bin.000003' , master_log_pos=194; start slave; show slave status\G 5.测试数据同步:主库创建数据库和表数据 create database xueuiying; use xuehuiying; create table xhy01 (id int,name varchar(40)); insert into xhy01 values (1,'xhy01' ),(2,'xhy02' ),(3,'xhy03' ); commit; select * from xhy01;+------+-------+ | id | name | +------+-------+ | 1 | xhy01 | | 2 | xhy02 | | 3 | xhy03 | +------+-------+ 备库检查 select * from xueuiying.xhy01;+------+-------+ | id | name | +------+-------+ | 1 | xhy01 | | 2 | xhy02 | | 3 | xhy03 | +------+-------+
传统异步复制的开关机步骤
1.主库关闭服务
2.从库等待数据写入完毕后 stop slave; 关闭服务,关机
3.开机,主机先启动服务,从库再启动服务
4.主从进行检查show slave status\G show processlist;
主从复制部署——(传统无损同步) 适合数据量少于100G
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 半同步或无损同步需要安装插件semisync_master.so 1.查看plugin_dir show variables like "plugin_dir" ; +---------------+------------------------------+ | Variable_name | Value | +---------------+------------------------------+ | plugin_dir | /usr/local/mysql/lib/plugin/ | +---------------+------------------------------+ 2.将插件文件放入该目录下 安装 (1)安装方式1,手动安装 install plugin rpl_semi_sync_master soname 'semisync_master.so' ; install plugin rpl_semi_sync_slave soname 'semisync_slave,so' ; (2)安装方式2,直接写入配置文件(建议) plugin_load="rpl_semi_sync_slave=semisync_slave.so;rpl_semi_sync_master=semisync_master.so" loose_rpl_semi_sync_master_enabled=1 loose_rpl_semi_sync_slave_enabled=1 loose_rpl_semi_sync_master_timeout=5000 rpl_semi_sync_master_wait_for_slave_count=1 rpl_semi_sync_master_wait_point=AFTER_SYNC 重启服务 show plugins; 3.从库重新进行指向 stop slave; change master to master_host='192.168.10.125' , master_user='repuser' , master_password='repuser123' , master_log_file='bin.000005' , master_log_pos=194; start slave; show slave status\G
semi相关参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 show variables like '%semi%' ;+ | Variable_name | Value | + | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 5000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_for_slave_count | 1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_SYNC | - 表示是无损同步,AFTER_COMMIT代表半同步| rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | + show status like '%semi%' ;+ | Variable_name | Value | + | Rpl_semi_sync_master_clients | 2 | - 客户端个数| Rpl_semi_sync_master_net_avg_wait_time | 0 | - 平均等待时间ms| Rpl_semi_sync_master_net_wait_time | 0 | - 总计等待时间| Rpl_semi_sync_master_net_waits | 0 | - 等待次数| Rpl_semi_sync_master_no_times | 0 | - 关闭半同步的次数| Rpl_semi_sync_master_no_tx | 0 | - 没有成功接受slave提交的次数| Rpl_semi_sync_master_status | ON | - 看从库on 半同步,off异步| Rpl_semi_sync_master_timefunc_failures | 0 | - 调用函数失败次数| Rpl_semi_sync_master_tx_avg_wait_time | 0 | - 事务平均传输时间| Rpl_semi_sync_master_tx_wait_time | 0 | - 事务总共传输时间| Rpl_semi_sync_master_tx_waits | 0 | - 事务等待次数| Rpl_semi_sync_master_wait_pos_backtraverse | 0 | - 后来的先到,先来的后到的次数| Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 0 | - 成功接受slave事务恢复的次数| Rpl_semi_sync_slave_status | OFF | - 看本库on 是半同步,off是异步+
主从复制部署——(GTID无损同步)(未完成) 主从复制部署——(GTID异步复制) 主库参数添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 bind-address=192.168.10.125 server-id=253306 skip_name_resolve=on expire_logs_days=7 innodb_flush_log_at_trx_commit=1 sync_binlog=1 transaction_isolation=READ-COMMITTED gtid_mode=on enforce_gtid_consistency=1 log_slave_updates=1 binlog_gtid_simple_recovery=1 log_bin=/usr/local/mysql/logs/bin.log log_bin_index=/usr/local/mysql/logs/binlog.index binlog_format=ROW binlog_rows_query_log_events=on max_binlog_size=2024M binlog_cache_size=1M plugin_load="rpl_semi_sync_slave=semisync_slave.so;rpl_semi_sync_master=semisync_master.so" rpl_semi_sync_master_timeout=5000 rpl_semi_sync_master_wait_for_slave_count=1 rpl_semi_sync_master_wait_point=AFTER_SYNC
从库参数添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 server-id和bind-address要修改 bind-address=192.168.10.126 server-id=263306 skip_name_resolve=on expire_logs_days=7 innodb_support_xa=1 innodb_flush_log_at_trx_commit=1 log_bin_trust_function_creators=1 sync_binlog=1 transaction_isolation=READ-COMMITTED gtid_mode=on enforce_gtid_consistency=1 log_slave_updates=1 binlog_gtid_simple_recovery=1 log_bin=/usr/local/mysql/logs/bin.log log_bin_index=/usr/local/mysql/logs/binlog.index binlog_format=ROW binlog_rows_query_log_events=on max_binlog_size=2024M binlog_cache_size=1M relay_log=/usr/local/mysql/logs/relay.log read_only=1 rpl_semi_sync_master_wait_for_slave_count=1 plugin_load="rpl_semi_sync_slave=semisync_slave.so;rpl_semi_sync_master=semisync_master.so;plugin-load=AUDIT=libaudit_plugin.so" rpl_semi_sync_master_timeout=5000 rpl_semi_sync_master_wait_point=AFTER_SYNC
创建复制用户并授权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 mysql -uroot -proot create user 'repuser'@'%' identified by 'repuser123'; grant replication client,replication slave on *.* to 'repuser'@'%'; flush privileges; select user,host from mysql.user; +---------------+-----------+ | user | host | +---------------+-----------+ | repuser | % | | root | % | | mysql.session | localhost | | mysql.sys | localhost | | root | localhost | +---------------+-----------+
从库上和主库建立连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #清空环境 stop slave; reset master; reset slave; #指向主库 change master to master_host='192.168.10.125', master_port=3306, master_user='repuser', master_password='repuser123', master_auto_position=1; #开启从库 start slave; show slave status\\G show processlist;
验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 主库进行修改: mysql -uroot -proot create database wsdb; use wsdb; create table wst1 (id int,name varchar(20)); insert into wst1 values(1,'ws1'),(2,'ws2'),(3,'ws3'); commit; select * from wsdb.wst1; +------+------+ | id | name | +------+------+ | 1 | ws1 | | 2 | ws2 | | 3 | ws3 | +------+------+ 备库验证: select * from wsdb.wst1; +------+------+ | id | name | +------+------+ | 1 | ws1 | | 2 | ws2 | | 3 | ws3 | +------+------+
补充:MASTER_DELAY参数 1 2 3 4 5 6 7 8 9 10 change master to [option] 常规选项 master_host master_user master_password master_log_file master_log_pos 延迟复制(秒)——在启动后n秒SQL线程才开始复制 MASTER_DELAY
报错处理 1 2 3 4 5 6 7 如果数据异常,需要清空环境从头来过 从库 stop slave; reset slave; reset slave all; 主库 reset master;
1.主从节点server-uuid一致报错 Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. 解决方法:停止从节点后,修改/usr/local/mysql/data/auto.cnf中的信息,并重启 也可以直接删除auto.cnf,重启后会自动生成
2.修改server-uuid报错 Error ‘Operation CREATE USER failed for ‘repuser‘@’%’’ on query. Default database: ‘’. Query: ‘CREATE USER ‘repuser‘@’%’ IDENTIFIED WITH ‘mysql_native_password’ AS ‘D6B70D90834FFD0E0516A62778445C486176C003’’ 解决方法:停止从节点后删除从节点所有binlog和bin-index
3.主从复制在sql语句执行错误时卡住 报错Error ‘Can’t drop database ‘wsdb02’; database doesn’t exist’ on query. Default database: ‘wsdb02’. Query: ‘drop database wsdb02’ 解决方法: 方法(1) 通过SHOW SLAVE STATUS\G或查看日志,找到错误事务的gtid,然后使用sql跳过事务 查看SHOW SLAVE STATUS\G Relay_Master_Log_File: bin.000001 Read_Master_Log_Pos: 1411 Exec_Master_Log_Pos: 537
mysqlbinlog –start-position=537 –stop-position=1411 /usr/local/mysql/logs/bin.000001 | grep -i gtid STOP SLAVE; SET GTID_NEXT=’错误事务的GTID’; BEGIN; COMMIT; SET GTID_NEXT=AUTOMATIC; START SLAVE SQL_THREAD;
方法(2) 重新指向时,指定 change master to master_host=’192.168.10.125’, master_port=3306, master_user=’repuser’, master_password=’repuser123’, master_auto_position=0; 相当于指定不适用gtid的方式进行主从复制
注意点:最好不要在初始化数据库阶段直接加入主从复制,因为像授权用户创建‘root‘@’%’这样的操作,从库接受但无法执行就会报错,此时就需要设置过滤器将其过滤掉