Mysql复制架构及主从复制中数据不一致的解决方案

一、MySQL 复制架构

  • Master/Slave主从架构
    • Master:主节点可读可写
    • Slaves: 从节点只读、不可写

1、主从架构的优点:

1、解决了冗余问题和异地灾备;
2、配合高可用工具程序MHA,提高可靠性;
3、解决负载均衡问题,转移一部分“读”请求;
4、支援安全的备份操作;
5、测试,主从复制提供实验环境;
...

2、主/从架构类型:

  • 异步复制:mysql复制过程就是异步的;

  • 半同步复制:当主节点完成写操作时候,此时会立即同步到一部分带宽较大的节点(此节点可提升为主节点),然后返回结果给客户,最后同步给其他节点;

  • 一主多从;一个主节点可以有多个从节点


    一主多从
  • 一从一主;默认时候是,一从节点 有一个一主节点,mysql5.X以后可以复制多个主节点中的不同数据库;

  • 级联复制;中继节点从主节点复制,其他从节点到中继节点复制,减少主节点复制压力;

  • 循环复制;多个主节点基于server id机制,循环复制事物;


    循环复制
  • 双主复制;两个主节点互相复制。

  • 一从多主:每个主服务器提供不同的数据库;

3、主从复制要考虑问题

  • 复制的开始位置是否从0开始;
  • 从备份中恢复到从节点后启动的复制,复制的起始点备份操作时主节点所处的日志文件及其事件位置;
  • 主从服务器mysqld程序版本不一致,从的版本号高于主的版本号;

二、主从复制示例

1、主服务器:

时间同步;

[root@mysql-19 ~]# ntpdate time1.aliyun.com

配置文件my.cnf

[root@mysql-19 ~]# vim /etc/my.cnf.d/server.cnf 
[mysqld]
innodb_file_per_table=ON
skip_name_resolve=ON

server_id=1
log_bin=log-bin

启动服务:

systemctl start mariadb.service

授权从服务器复制账号

MariaDB [(none)]> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'repluser'@'192.168.1.20' IDENTIFIED BY 'replpass';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
#查看二进制日志信息
MariaDB [(none)]> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-log.000001 |      245 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

2、从服务器:

时间同步;

[root@mysql-19 ~]# ntpdate time1.aliyun.com

配置文件my.cnf

[root@mysql-20 ~]# vim /etc/my.cnf.d/server.cnf 
[mysqld]
innodb_file_per_table=ON
skip_name_resolve=ON

server_id=12
relay_log=relay-log
read_only=ON

启动服务:

systemctl start mariadb.service

设置从服务器复制

[root@mysql-20 ~]# mysql

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.1.19',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_PORT=3306,MASTER_LOG_FILE='master-log.000001',MASTER_LOG_POS=245;
Query OK, 0 rows affected (0.05 sec)
#启动线程进行复制
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
#查看
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.19
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-log.000001
          Read_Master_Log_Pos: 498
               Relay_Log_File: relay-log.000002
                Relay_Log_Pos: 783
        Relay_Master_Log_File: master-log.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 498
              Relay_Log_Space: 1071
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
1 row in set (0.01 sec)

3、测试:

#主数据库操作
MariaDB [(none)]> create database mydb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> use mydb;
Database changed

MariaDB [mydb]> CREATE TABLE tbl1(id INT,name CHAR(30),age INT);
Query OK, 0 rows affected (0.33 sec)

#从数据库查询是否同步
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.01 sec)

MariaDB [(none)]> use mydb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mydb]> show tables;
+----------------+
| Tables_in_mydb |
+----------------+
| tbl1           |
+----------------+
1 row in set (0.00 sec)

MariaDB [mydb]> desc tbl1;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  |     | NULL    |       |
| name  | char(30) | YES  |     | NULL    |       |
| age   | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)

三、主主复制:

  • 互为主从:两个节点各自都要开启binlog和relay log;
  • 需要解决数据不一致和自动增长id问题;
定义一个节点使用奇数id

auto_increment_offset=1 #起始偏移值
auto_increment_increment=2 #步进值

另一个节点使用偶数id

auto_increment_offset=2 #起始偏移值
auto_increment_increment=2 #步进值

1、节点一服务器配置:

[root@mysql-19 ~]# vim /etc/my.cnf.d/server.cnf 
[mysqld]
innodb_file_per_table=ON
skip_name_resolve=ON

server_id=1
log-bin=master-log
relay_log=relay-log

auto_increment_offset=1 #起始偏移值
auto_increment_increment=2  #步进值
[root@mysql-19 ~]# systemctl start mariadb
[root@mysql-19 ~]# mysql
#复制授权
MariaDB [(none)]> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'repluser'@'192.168.1.20' IDENTIFIED BY 'replpass';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
#查看二进制日志位置
MariaDB [(none)]> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-log.000003 |      770 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

#设置访问节点二用户名密码
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.1.20',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_PORT=3306,MASTER_LOG_FILE='master-log.000003',MASTER_LOG_POS=770;
Query OK, 0 rows affected (0.01 sec)
#启动复制
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)

2、节点二配置:

[mysqld]
innodb_file_per_table=ON
skip_name_resolve=ON

server_id=12
log_bin=master-log
relay-log=relay-log
read_only=ON

auto_increment_offset=2
auto_increment_increment=2

#从服务器访问授权
MariaDB [(none)]> GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'repluser'@'192.168.1.19' IDENTIFIED BY 'replpass';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
#设置访问节点一用户名密码
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.1.19',MASTER_USER='repluser',MASTER_PASSWORD='replpass',MASTER_PORT=3306,MASTER_LOG_FILE='master-log.000003',MASTER_LOG_POS=770;
Query OK, 0 rows affected (0.06 sec)
#查看二进制日志位置
MariaDB [(none)]> show master status;
+-------------------+----------+--------------+------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-log.000003 |      770 |              |                  |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
#启用复制
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)

3、测试:

#节点一操作:创建mydb数据库,待节点二创建完表后,再次查询
MariaDB [(none)]> create database mydb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

MariaDB [(none)]> use mydb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [mydb]> show tables;
+----------------+
| Tables_in_mydb |
+----------------+
| tbl1           |
+----------------+
1 row in set (0.00 sec)

MariaDB [mydb]> desc tbl1;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | int(11)  | YES  |     | NULL    |       |
| name  | char(30) | YES  |     | NULL    |       |
| age   | int(11)  | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec)
#节点二操作:在mydb库中创建表
MariaDB [(none)]> use mydb;
Database changed
MariaDB [mydb]> CREATE TABLE tbl1(id INT,name CHAR(30),age INT);
Query OK, 0 rows affected (0.06 sec)

4、配置注意:
  • server_id必须要使用不同值;
  • 均启用binlog和relay log;
  • 存在自动增长id的表,为了使得id不相冲突,需要定义其自动增长方式;

5、服务启动后执行如下两步:

  • 所有节点都授权有复制权限的用户账号;
  • 各把对方指定为主节点;
6、复制时应该注意的问题:
  • (1)从服务设定为“只读”;
    在从服务器启动read_only,但仅对非SUPER权限的用户有效;

  • (2)尽量确保复制时的事务安全
    在master节点启用参数:
    sync_binlog = ON
    如果用到的是InnoDB存储引擎:
    innodb_flush_logs_at_trx_commit=ON
    innodb_support_xa=ON

  • (3)、从服务器意外中止时尽量避免自动启动复制线程

  • (4)、从节点:设置参数
    sync_master_info=ON 同步到磁盘
    sync_relay_log_info=ON

四、半同步复制

  • google为mysql提供的插件

  • 支持多种插件:/usr/lib64/mysql/plugins/

  • 需要安装方可使用:

mysql> INSTALL PLUGIN plugin_name SONAME 'shared_library_name';
  • 半同步复制:
    semisync_master.so 主节点半同步插件
    semisync_slave.so 从节点半同步插件

1、主节点:

#安装主节点半同步插件
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#查询主节点半同步插件状态
MariaDB [mydb]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | OFF   |  #启用状态
| rpl_semi_sync_master_timeout       | 10000 |  #等待从节点返回值超时时长
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
#启用主节点半同步插件
MariaDB [mydb]> SET @@global.rpl_semi_sync_master_enabled=ON;

2、从节点:

#安装从节点半同步插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
#查看从节点半同步插件当前状态
MariaDB [mydb]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
#启用从节点半同步插件
MariaDB [mydb]> SET @@global.rpl_semi_sync_slave_enabled=ON;
#查看从节点半同步插件当前状态
MariaDB [mydb]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%';
#重启线程
MariaDB [mydb]> STOP SLAVE IO_THREAD;
MariaDB [mydb]> START SLAVE IO_THREAD;

3、测试:

主节点:

MariaDB [(none)]> SHOW GLOBAL STATUS LIKE 'rpl%';
+--------------------------------------------+-------------+
| 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             | 0           |  #等待次数
| 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      | 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           |
| Rpl_status                                 | AUTH_MASTER |
+--------------------------------------------+-------------+
15 rows in set (0.00 sec)

五、复制过滤器:

  • 仅复制有限一个或几个数据库相关的数据,而非所有;由复制过滤器进行;

有两种实现思路:

1、主服务器端过滤

  • 主服务器仅向二进制日志中记录有关特定数据库相关的写操作;
    问题:其它库的time-point recovery将无从实现,只能到库级别过滤,不建议使用此种过滤方法;
注意:过滤设置不能同时使用。

binlog_do_db= 仅对某个库有写权限(白名单)
binlog_ignore_db= 除此库之外的所有有写权限(黑名单)

2、从服务器端过滤

  • 从服务器的SQL THREAD仅重放关注的数据库或表相关的事件,并将其应用于本地;
    问题:因为要把主节点的所有库都复制过来,然后再过滤需要的库和表进行重放,所以无用的复制占用了网络IO和磁盘IO;

Replicate_Do_DB= 库级别白名单
Replicate_Ignore_DB= 库级别黑名单
Replicate_Do_Table= 表级别黑名单
Replicate_Ignore_Table= 表级别黑名单
Replicate_Wild_Do_Table= 使用通配符匹配白名单
Replicate_Wild_Ignore_Table= 使用通配符匹配黑名单

从服务器:

#查询从节点相关设置信息
MariaDB [(none)]> SHOW SLAVE STATUS \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.19
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-log.000004
          Read_Master_Log_Pos: 245
               Relay_Log_File: relay-log.000005
                Relay_Log_Pos: 530
        Relay_Master_Log_File: master-log.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:    #库级别白名配置
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
.......
#查询库级别白名单配置
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%do_db%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| replicate_do_db |       |
+-----------------+-------+
1 row in set (0.00 sec)
#停止从节点复制线程
MariaDB [(none)]> stop slave;
Query OK, 0 rows affected (0.01 sec)
#设置库白名单启用
MariaDB [(none)]> SET @@global.replicate_do_db=mydb;
Query OK, 0 rows affected (0.00 sec)
#启用从节点复制线程
MariaDB [(none)]> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)
#查询从节点设置信息
MariaDB [(none)]> SHOW SLAVE STATUS \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.19
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-log.000004
          Read_Master_Log_Pos: 245
               Relay_Log_File: relay-log.000005
                Relay_Log_Pos: 530
        Relay_Master_Log_File: master-log.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: mydb   #设置成mydb库
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
           .................

六、复制的监控和维护:

1、清理日志:PURGE

格式:PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr };

#备份二进制日志文件
[root@mysql-19 ~]# mkdir /data/backup/binlogs -pv
mkdir: created directory ‘/data/backup/binlogs’
[root@mysql-19 ~]# cp /var/lib/mysql/master-log.* /data/backup/binlogs/


MariaDB [(none)]> show master logs;
+-------------------+-----------+
| Log_name          | File_size |
+-------------------+-----------+
| master-log.000001 |     30340 |
| master-log.000002 |   1038814 |
| master-log.000003 |       498 |
| master-log.000004 |       245 |
+-------------------+-----------+
4 rows in set (0.00 sec)
#删除00004之前的日志
MariaDB [(none)]> PURGE MASTER LOGS TO 'master-log.000004';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show master logs;
+-------------------+-----------+
| Log_name          | File_size |
+-------------------+-----------+
| master-log.000004 |       245 |
+-------------------+-----------+
1 row in set (0.00 sec)
#自动更新index文件
[root@mysql-19 ~]# cat /var/lib/mysql/master-log.index 
./master-log.000004

2、 复制监控语句
  • MASTER:显示主节点信息
SHOW MASTER STATUS \G;
SHOW BINLOG EVENTS; #查询二进制文件数据记录位置
SHOW BINARY LOGS; #查询二进制文件
  • SLAVE:显示从节点信息
SHOW SLAVE STATUS \G;
  • 判断从服务器是否落后于主服务器:
Seconds_Behind_Master: 0
3、 如何确定主从节点数据是否一致

通过表的CHECKSUM检查;
使用percona-toolkit中pt-table-checksum命令;

  • 用途: 可以用来检测主、 从数据库中数据的一致性。
  • 原理: 在主库上运行, 对同步的表进行checksum, 记录下来。 然后对比主从中各个表的checksum是否一致, 从而判断数据是否一致。
注意:
1、根据测试,需要一个技能登录主库,也能登录从库,而且还能同步数据库的账号;
2、只能指定一个host,必须为主库的IP;
3、在检查时会向表加S锁;
4、运行之前需要从库的同步IO和SQL进程是YES状态。
#下载
[root@mysql-20 ~]# wget https://www.percona.com/downloads/percona-toolkit/3.0.12/binary/redhat/7/x86_64/percona-toolkit-3.0.12-1.el7.x86_64.rpm
#安装
[root@mysql-20 ~]# yum install percona-toolkit-3.0.12-1.el7.x86_64.rpm -y
#校验
[root@mysql-20 ~]# pt-table-checksum h=192.168.1.19,u=myadmin,p=mypass,P=3306 --databases=mysql --tables=tbl3 --nocheck-replication-filters 
#结果
.............
# A software update is available:
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
11-03T18:51:23      0      0        3          0       1       0   0.035 mysql.tbl3
............

参数说明:

TS            :完成检查的时间。
ERRORS        :检查时候发生错误和警告的数量。
DIFFS         :0表示一致,1表示不一致。当指定--no-replicate-check时,会一直为0,当指定--replicate-check-only会显示不同的信息。
ROWS          :表的行数。
CHUNKS        :被划分到表中的块的数目。
SKIPPED       :由于错误或警告或过大,则跳过块的数目。
TIME          :执行的时间。
TABLE         :被检查的表名。

参数意义:
--nocheck-replication-filters :不检查复制过滤器,建议启用。后面可以用--databases来指定需要检查的数据库。
--no-check-binlog-format      : 不检查复制的binlog模式,要是binlog模式是ROW,则会报错。
--replicate-check-only :只显示不同步的信息。
--replicate=   :把checksum的信息写入到指定表中,建议直接写到被检查的数据库当中。
--databases=   :指定需要被检查的数据库,多个则用逗号隔开。
--tables=      :指定需要被检查的表,多个用逗号隔开
h=127.0.0.1    :Master的地址
u=root         :用户名
p=123456       :密码
P=3306         :端口

参数解释:
# --h -u -p -P -S -d 连接信息
# --nocheck-replication-filters 检测中忽略mysql 配置参数binlog_ignore_db等
# --nocheck-binlog-format 不检测日志格式
# --replicate 指定checksum 存储的db和表, 如:pt.checksum
# --databases 指定数据库,如:nobserver_new
# --chunk-size, --chunk-size-limit 用于指定检测块的大小,可控性更强
# --ignore-databases/tables/column 跳出指定元素的过滤
# --lock-wait-timeout innodb 锁的超时设定, 默认为1
# --max-load 设置最大并发连接数
# --replicate-check-only 只输出数据不一致的信息

#更多的参数请见官网,上面指出来的是常用的,对该场景够用的参数。
#通过DIFFS是1可以看出主从的表数据不一致,通过查看从库上的test.checksum表可以看到主从库的检验信息。
#当DIFFS列全部为0时表示Master、Slave无差异。
4、 主从数据不一致时的修复方法
方法一:

重新复制数据库,结合二进制文件恢复。

方法二:
  • pt-table-sync修复从库不一致的数据
    使用方法:pt-table-sync [OPTIONS] DSN [DSN]
  • pt-table-sync: 高效的同步MySQL表之间的数据,它可以做单向和双向同步的表数据。可以同步单个表,也可以同步整个库。它不同步表结构、索引、或任何其他模式对象。所以在修复一致性之前需要保证它们表存在。
#同步主从数据
[root@mysql-20 ~]# pt-table-sync --print --replicate=test.checksum h=192.168.1.21,u=myadmin,p=mypass,P=3306 h=192.168.1.19,u=myadmin,p=mypass,P=3306 #第一个ip是主节点,第二个ip是从节点
#或者
#用一个从节点ip执行同步库里的指定表
[root@mysql-20 bin]# pt-table-sync --print --sync-to-master h=192.168.1.19,u=myadmin,p=mypass,P=3306 --databases mysql --tables tbl3

参数的意义:
--replicate=  :指定通过pt-table-checksum得到的表,这2个工具差不多都会一直用。
--databases=  : 指定执行同步的数据库,多个用逗号隔开。
--tables=     :指定执行同步的表,多个用逗号隔开。
--sync-to-master :指定一个DSN,即从的IP,他会通过show processlist或show slave status 去自动的找主。
h=127.0.0.1   :服务器地址,命令里有2个ip,第一次出现的是M的地址,第2次是Slave的地址。
u=root        :帐号。
p=123456      :密码。
--print       :打印,但不执行命令。
--execute     :执行命令。

更多的参数请见官网,上面指出来的是常用的,对该场景够用的参数

注意:要是表中没有唯一索引或则主键则会报错:
Can't make changes on the master because no unique index exists at /usr/local/bin/pt-table-sync line 10591.

七、读锁FTWRL在备份中的使用

  • 当你使用逻辑方式进行备份(mydumper,mysqldump)或物理方式进行备份(percona-xtrabackup),为了保证数据的一致性,这两种备份方式都会在备份过程中执行 flush table with read lock 这个命令(以下简称为FTWRL),通过执行FTWRL,来对事务和非事务表来加table level级别的共享锁,取得此时的gtid或者binlog偏移量,继而得到某一个时间点的备份数据。
读锁的作用

flush tables with read lock的作用是关闭所有打开的表,同时对于所有数据库中的表都加一个读锁,直到显示地执行unlock tables,该操作常常用于数据备份的时候也就是将所有的脏页都要刷新到磁盘,然后对所有的表加上了读锁,于是这时候直接拷贝数据文件也就是安全的。

工作流程
  • 第一步的作用是堵塞更新,备份时,我们期望获取此时数据库的一致状态,不希望有更多的更新操作进来。对于innodb引擎而言,其自身的MVCC机制,可以保证读到老版本数据,因此第一步对它使多余的。
  • 第二步,清理表缓存,这个操作对于myisam有意义,关闭myisam表时,会强制要求表的缓存落盘,这对于物理备份myisam表是有意义的,因为物理备份是直接拷贝物理文件。对于innodb表,则无需这样,因为innodb有自己的redolog,只要记录当时LSN,然后备份LSN以后的redolog即可。
  • 第三步,主要是保证能获取一致性的binlog位点,这点对于myisam和innodb作用是一样的。

读锁缺点:

  • 由于FTWRL总共需要持有两把全局的MDL锁,并且还需要关闭所有表对象,因此这个命令的杀伤性很大,执行命令时容易导致库hang住。如果是主库,则业务无法正常访问;如果是备库,则会导致SQL线程卡住,主备延迟。

改进

  • 在 5.6.16-64.0这个版本中,percona开始引入了两个新的MDL类型的锁,相应的引入了两个新的备份命令

LOCK TABLES FOR BACKUP
LOCK BINLOG FOR BACKUP

  • lock tables for backup
      执行该命令后,获得的新的MDL锁会阻塞对非事务表的更新及所有DDL动作,此时其他用户可以继续更新inonodb引擎的表,但是无法对myisam表进行更新动作。
  • lock binglog for backup
      执行该命令后,如果加锁成功,将会阻塞binglog的更新,此时所有的DML操作被阻塞。
    参考文献:https://www.cnblogs.com/cchust/p/4603599.html
    https://www.cnblogs.com/conanwang/p/6925108.html
    https://www.cnblogs.com/sunss/archive/2012/02/02/2335960.html
    http://www.freeoa.net/osuport/db/chk-and-rep-mysql-msprob-by-percona-toolkit_3098.html

你可能感兴趣的:(Mysql复制架构及主从复制中数据不一致的解决方案)