MariaDB GTID复制

一.环境信息
主库:168.24.65.30
从库:168.24.65.31、168.24.65.32
mariadb 10.1.16

二,搭建传统复制(可选)
先在主库上查看:
mysql -uroot -p --socket=/tmp/mysql3306.sock
(product)root@localhost [(none)]> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 |      343 |              |                  |
+------------------+----------+--------------+------------------+

从库上执行:
change master to
master_host='168.24.65.30',
master_port=3306,
master_user='rep',
master_password='xxxx',
master_log_file='mysql-bin.000002',
master_log_pos=343;
start slave;

三.搭建GTID复制
目前我们生产环境主要是由两种方式进行备份:
1、mydumper备份
可以到备份目录文件下获取备份完成时主库最后执行的事务的GTID.
Started dump at: 2017-06-17 10:55:40
SHOW MASTER STATUS:
Log: mysql-bin.000056
Pos: 9637
GTID:0-64236-299476
GTID:0-64236-299476 就是后面从库导入备份数据后,从这个GTID开始进行复制的位置。
2、xtrabackup备份
more xtrabackup_binlog_info 
mysql-bin.000104 95830984 0-691253306-60596652
0-691253306-60596652 是后面从库数据导入后进行复制的起始位置。
从库导入备份数据(mydumper或者xtrabackup备份)后,执行以下步骤
a. set global gtid_slave_pos='0-64236-299476';
b. show variables like 'gtid%';确认gtid_slave_pos位置有效。
MariaDB [jira]> show variables like 'gtid%'; 
+------------------------+----------------+
| Variable_name | Value |
+------------------------+----------------+
| gtid_binlog_pos | |
| gtid_binlog_state | |
| gtid_current_pos | 0-64236-299476 |
| gtid_domain_id | 0 |
| gtid_ignore_duplicates | OFF |
| gtid_seq_no | 0 |
| gtid_slave_pos | 0-64236-299476 |
| gtid_strict_mode | OFF |
+------------------------+----------------+
c. change master to master_host='168.24.65.30',master_user='rep',master_password='xxx',master_use_gtid=slave_pos;
d.start slave; show slave status\G 确认复制搭建成功。
MariaDB [jira]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 168.24.65.30
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000056
Read_Master_Log_Pos: 9637
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 670
Relay_Master_Log_File: mysql-bin.000056
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...
Master_Server_Id: 64236
Master_SSL_Crl: 
Master_SSL_Crlpath: 
Using_Gtid: Slave_Pos
Gtid_IO_Pos: 0-64236-299476


四,传统与GTID复制切换
1、传统复制切换到GTID复制
stop slave;
change master to master_use_gtid=slave_pos;或者执行 change master to master_use_gtid=current_pos
start slave;
show slave status\G 确认复制已经切换成功
2.GTID复制切换到传统复制
stop slave;
change master to master_use_gtid=no;
start slave;
shwo slave status\G Using_Gtid: No 可以确认已经由GTID复制切换到传统复制。

五、主从GTID复制结构中Master切换
A(M)-->B(S) 切换为 A(S)<--B(M) 结构
主从GTID复制结构中Master切换非常简单。
1、先确认从库B已经完全追上主库A
Master_Log_File: mysql-bin.000002 = Relay_Master_Log_File:mysql-bin.000002 && Read_Master_Log_Pos:343 = Exec_Master_Log_Pos: 343 
2、A 上执行
change master to master_host='B',master_port=,master_user='xxxx',master_password='xxx',master_use_gtid=current_pos;start slave;
这里把 master_use_gtid 配置成 current_pos。
因为该主库没有做过其他数据库的从库,所以slave_pos为空,需要用current_pos。二者区别可以看后面的定义。
3、B 上执行 stop slave;
一主多从结构的主库切换和一主一从切换类似,只要把原来的从库直接change到新的主库上面就好。

六、在使用GTID的从服务器中跳过事务
场景:
在从库某表中删掉某条记录,然后在主库上执行同样的删除动作。
从库上操作:
(product)root@localhost > delete from abc where id=2;
Query OK, 1 row affected (0.00 sec)

主库操作:
delete from abc  where id=2;

这时从库会报错如下:
Last_Errno: 1032
Last_Error: Could not execute Delete_rows_v1 event on table abc; Can't find record in 'abc', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000002, end_log_pos 906

从库找不到需要删除的记录,这时可以手动跳过这个错误。
方法1:
show slave status\G
Gtid_IO_Pos: 0-303306-27108734


stop slave; set global gtid_slave_pos='0-303306-27108734';start slave; 
show slave status\G 确认主从复制恢复正常。
方法2:
stop slave;set global sql_slave_skip_counter=1;start slave;
show slave status\G 确认主从复制恢复正常。

七、GTID使用限制
1、slave的本地写入,需要注意,因为跟master不是同一个GTID范围,写入binlog的值,复制到后续从库,容易失败,需要使用
set sql_log_bin=0,来禁止binlog的写入。
生产环境所有从库已经设置为read_only(普通用户只有select权限,有all/super权限的都不在这个范围内)。如果因为特殊情况需要在从库
写入数据,则先临时关闭binlog写入。
2、切换主库前,必须保证主库数据已经全部复制到将要作为新主库的从库。
3、不能在事务中创建和删除临时表;
4、无法在事务中对非事务存储引擎进行更新;
5、限制mysql_upgrade的执行;
八、常见复制错误处理
1、主库进行update,delete操作,从库发现没有相应记录,导致复制中断。
Last_SQL_Error: Could not execute Delete_rows_v1 event on table test.tt; Can't find record in 'tt', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000056, end_log_pos 10508
处理方式:
根据复制报错的binlog位置,在主库上解析相应的binlog,确认从库具体因为哪些数据确失导致复制中断。
找出从库缺失的记录之后手动从主库导出,再导入从库。导入的时候,切记要先关闭binlog写入。
set sql_log_bin=0;导入数据;set sql_log_bin=1; 然后重启复制。
2、主库上执行 insert操作,从库已经有相应的记录,导致复制中断。
从库报错如下:
Last_SQL_Error: Could not execute Write_rows_v1 event on table test.tt; Duplicate entry '12' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000056, end_log_pos 10907
处理方式:
根据报错信息可以知道从库已经存在ID=12的记录,因此复制再次插入同样主键ID记录时,报1062错误。
为了验证这一点,可以解析主库相应位置的binlog。
因此我们可以直接删除从库ID=12的记录,重启复制。
以上错误除了主库delete操作,从库因记录缺失报错可以跳过。其他错误都不能直接跳过,会导致主从数据不一致。
七、GTID有关的三个全局变量
select @@global.gtid_slave_pos, @@global.gtid_binlog_pos,@@global.gtid_current_pos;
gtid_slave_pos:
This variable is the GTID of the last event group replicated on a slave server, for each replication domain.
gtid_binlog_pos:
This variable is the GTID of the last event group written to the binary log, for each replication domain.
gtid_current_pos:
This variable is the GTID of the last change to the database for each replication domain. Such changes can either be master events (ie. local changes made by user or application), or replicated events originating from another master server.
总结
MariaDB10.0.2之后的GTID复制搭建与管理非常方便,整体比MySQL官方版本好用很多。
主要有以下优势:
1、MariaDB GTID可以有间断,支持 set global sql_slave_skip_counter=1 跳过错误的语法。
MySQL的GTID是连续的,不支持直接跳过错误的语法,只能采取插入空事务来跳过相应的GTID.
2、MariaDB 复制结构中可以同时混杂传统复制从库和GTID复制从库。但是MySQL不行,必须所有数据库都开启GTID复制。
3、MariaDB GTID和传统复制间的切换是非常方便的无需其他配置。而MySQL就繁琐很多,无法做到平滑过渡,需要修改主库配置并重启。
MariaDB官方文档也推荐使用GTID复制。后续会琢磨一下GTID复制下的高可用工具,目标使MariaDB GTID复制在主库失败的情况下能自动切换,同时不丢失数据。
可支持create table tablename as select语句,测试如下:

CREATE TABLE bak_170728901_go (`_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键',PRIMARY KEY (`_id`))
AS
   SELECT * FROM  go;

Query OK, 43499 rows affected (3.83 sec)
Records: 43499  Duplicates: 0  Warnings: 0
发布了197 篇原创文章 · 获赞 23 · 访问量 48万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章