美文网首页
使用pt-table-checksum检测MySQL主从数据一致

使用pt-table-checksum检测MySQL主从数据一致

作者: 其实我很dou | 来源:发表于2018-08-08 17:09 被阅读0次

    1.环境:


    主库 10.101.67.15

    从库 10.101.67.13 10.101.67.14 10.10.32.20

    2.安装checksum


    安装依赖

    yum install perl perl-devel perl-Time-HiRes perl-DBI perl-DBD-MySQL perl-Digest-MD5

    安装工具

    wget http://www.percona.com/get/percona-toolkit.tar.gz

    tar zxf percona-toolkit.tar.gz

    cd percona-toolkit-version

    perl Makefile.PL

    make && make install

    3. 主库创建数据库以及用户账号


    3.1 创建数据库

    Create database pt CHARACTER SET utf8;

    3.2 创建用户checksum并授权

    GRANT ALL ON *.* TO 'checksum'@'10.101.67.15' IDENTIFIED BY 'checksum';

    flush privileges;

    3.3 创建测试数据表

    
    use pt;
    
    CREATE TABLE IF NOT EXISTS checksums (
    
    db char(64) NOT NULL,
    
    tbl char(64) NOT NULL,
    
    chunk int NOT NULL,
    
    chunk_time float NULL,
    
    chunk_index varchar(200) NULL,
    
    lower_boundary text NULL,
    
    upper_boundary text NULL,
    
    this_crc char(40) NOT NULL,
    
    this_cnt int NOT NULL,
    
    master_crc char(40) NULL,
    
    master_cnt int NULL,
    
    ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    PRIMARY KEY (db, tbl, chunk),
    
    INDEX ts_db_tbl (ts, db, tbl)
    
    ) ENGINE=InnoDB;
    

    进行checksum

    4.1 准备数据

    手动更改13库数据

    628950fdb328ee492595ed44a2bf0673.png

    更改14库表数据


    fcb1eae0b01de076ea6cb45778aa4d77.png

    更改20库表数据


    4e11b90a78de9112b3cd87c89f706c37.png

    4.2 进行checksum

    在主库所在机器编写脚本

    checksum.sh

    *******************************************************************

    #!/bin/bash
    
    date >> /root/db/checksum.log
    
    pt-table-checksum --nocheck-binlog-format --nocheck-plan
    --nocheck-replication-filters --replicate=pt.checksums --set-vars
    innodb_lock_wait_timeout=120 --databases UAR_STATISTIC -u'checksum' -p'checksum'
    -h'10.101.67.15' >> /root/db/checksum.log
    
    date >> /root/db/checksum.log
    

    执行: nohup sh checksum.sh &

    4.3 检查checksum.log, 查看结果

    
    Thu Aug 2 09:50:59 CST 2018
    
    Checking if all tables can be checksummed ...
    
    Starting checksum ...
    
    TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE
    
    08-02T09:51:00 0 1 48955 0 5 0 0.738 UAR_STATISTIC.app_activity_user_at_appv_day
    
    08-02T09:51:00 0 1 66733 0 1 0 0.481
    UAR_STATISTIC.app_activity_user_at_channel_appv_day
    
    08-02T09:51:01 0 1 53902 0 1 0 0.404
    UAR_STATISTIC.app_activity_user_at_channel_day
    
    08-02T09:51:01 0 0 36672 0 1 0 0.312 UAR_STATISTIC.app_activity_user_at_day
    
    08-02T09:51:04 0 0 162417 0 1 0 3.144
    UAR_STATISTIC.app_at_appv_country_operator_day
    
    08-02T09:51:08 0 0 235261 0 5 0 4.057 UAR_STATISTIC.app_at_appv_country_prov_day
    
    08-02T09:51:09 0 0 17961 0 1 0 0.379 UAR_STATISTIC.app_at_appv_day
    
    .....
    
    Thu Aug 2 10:26:10 CST 2018
    

    检查15G SQL数据总共执行花费了36分钟, 检查出不同的行有三行

    1. 校验结果核查

    登录三台机器的从库, 在各从库执行如下命令, 可以看出哪个数据库的哪张表不一致

    USE pt;

    SELECT db, tbl, SUM(this_cnt) AS total_rows, COUNT(*) AS chunks
    FROM checksums
    WHERE ( master_cnt <> this_cnt OR master_crc <> this_crc OR
    ISNULL(master_crc) <> ISNULL(this_crc) ) AND db = 'UAR_STATISTIC'
    GROUP BY db, tbl;

    5.1 机器13

    82dbf0a616fd755a3763c0c2d8ed067f.png

    5.2 机器14

    2be06597c9da01ce617d81cdfd38b958.png

    5.3 机器20

    a53ea976516702b215b093dac77b36ab.png
    1. 修复不一致

    6.1 打印修复语句

    找到不一致的从库以及表执行如下命令,
    .打印出sql语句,人工干预到Slave库执行(推荐)

    6.1.1 机器13

    pt-table-sync --print --sync-to-master
    h=10.101.67.13,P=3306,u=checksum,p=checksum --databases=UAR_STATISTIC
    --replicate=pt.checksums;

    执行结果

    [root@node3 db]# pt-table-sync --print --sync-to-master
    h=10.101.67.13,P=3306,u=checksum,p=checksum --databases=UAR_STATISTIC
    --replicate=pt.checksums;

    输出结果:

    REPLACE INTO `UAR_STATISTIC`.`app_activity_user_at_appv_day`(`at`,
    `appv`, `day`, `activity_user`, `total_user`) VALUES ('', 'v19.36',
    '20170429', NULL, '1') /*percona-toolkit src_db:UAR_STATISTIC
    src_tbl:app_activity_user_at_appv_day
    src_dsn:P=3306,h=10.101.67.15,p=...,u=checksum dst_db:UAR_STATISTIC
    dst_tbl:app_activity_user_at_appv_day
    dst_dsn:P=3306,h=10.101.67.13,p=...,u=checksum lock:1 transaction:1
    changing_src:pt.checksums replicate:pt.checksums bidirectional:0 pid:24190
    user:root host:node3*/;

    在13数据库执行提示sql

    REPLACE INTO `UAR_STATISTIC`.`app_activity_user_at_appv_day`(`at`,
    `appv`, `day`, `activity_user`, `total_user`) VALUES ('', 'v19.36',
    '20170429', NULL, '1')

    即可修复数据不一致问题

    6.1.2 机器14和20

    同理可以执行如下语句, 打印出修复sql, 在各从库MySQL执行, 从而修复

    pt-table-sync --print --sync-to-master
    h=10.101.67.14,P=3306,u=checksum,p=checksum --databases=UAR_STATISTIC
    --replicate=pt.checksums;

    pt-table-sync --print --sync-to-master
    h=10.10.32.20,P=3306,u=checksum,p=checksum --databases=UAR_STATISTIC
    --replicate=pt.checksums;

    6.2 自动修复

    在上边三条语句里添加 --execute 选项 ,将自动修复

    pt-table-sync --print --sync-to-master
    h=10.10.32.20,P=3306,u=checksum,p=checksum –-execute --databases=UAR_STATISTIC
    --replicate=pt.checksums;

    6.3 重新校验

    手动修复后, 重新校验, 查看是否还有不一致的数据

    7. 校验原理以及风险


    它通过在主库执行基于statement的sql语句来生成主库数据块的checksum,把相同的sql语句传递到从库,并在从库上计算相同数据块的checksum,最后,比较主从库上相同数据块的checksum值,由此判断主从数据是否一致。这种校验是分表进行的,在每个表内部又是分块进行的,而且pt工具本身提供了非常多的限流选项,检测时会自动判断复制延迟、
    master的负载, 超过阀值后会自动将检测暂停,减小对线上服务的影响。

    7.1 数据块checksum值的计算

    如果一行一行的计算checksum再去和从库比较,那么效率会非常低下。pt工具选择智能分析表上的索引,然后把表的数据split成一个个chunk,计算的时候也是以chunk为单位。因此引入了聚合函数BIT_XOR()。它的功能可以理解为把这个chunk内的所有行的数据拼接起来,再计算crc32的值,就得到这个chunk的checksum值。sql语句如下:
    这其中还有count(*),用来计算chunk包含的行数。每一次对chunk进行checksum后,pt工具都会对耗时进行统计分析,并智能调整下一个chunk的大小,避免chunk太大对线上造成影响,同时也要避免chunk太小而效率低下。

    7.2 一致性如何保证

    当pt工具在计算主库上某chunk的checksum时,主库可能还在更新,同时从库可能延迟使得relay-log中还有与这个chunk数据相关的更新,那该怎么保证主库与从库计算的是”同一份”数据?答案是加for
    update当前读锁,这保证了主库的某个chunk内部数据的一致性。否则,1000个人chekcusm同样的1000行数据,可能得到1000个不同的结果,你无法避开mvcc的干扰!获得for
    update锁后,pt工具开始计算chunk的checksum值,并把计算结果保存到pt工具自建的结果表中(采用replace
    into select的方式),然后释放锁。该语句最终会传递到从库并执行相同的计算逻辑。

    7.3 风险

    pt-table-checksum 不是对一个表仅作一个校验和,因为如果表特别大,将会对DB造成很大的负载,影响正常业务。一个表一个校验和就退化到mysql自带命令CHECKSUM
    TABLE了,不仅需要锁表,而且不准确。pt-table-checksum将表按用户设置的块大小,将表分成若干份,然后对每个块计算一个校验和。这样即使表特别大,分块后也只会锁住部分记录,对DB的负载压力也大大降低。由于多个表校验可以并发,可以大大提高校验效率,通过参数-max-load可以防止load过大。

    pt-table-checksum基本能满足我们的日常需求,但是它还有一些需要完善的地方,首先,仅仅支持表粒度的并发,当检查一个大表时,需要耗费大量的时间,另外多表并行执行时,并行度也不能通过参数的设置,而是通过--max-load间接设置。其次,通过分块生成校验和虽然加快了校验速度,但1000行算一个4字节的校验值(默认是一个块1000行),产生冲突的可能性很大,即使pt-table-checksum设计的校验和算法很复杂。

    附录: 参考博客:

    https://blog.csdn.net/melody_mr/article/details/45224249

    https://www.cnblogs.com/cchust/p/3521650.html

    https://www.cnblogs.com/erisen/p/5971420.html

    https://www.cnblogs.com/huminxxl/p/3978559.html

    相关文章

      网友评论

          本文标题:使用pt-table-checksum检测MySQL主从数据一致

          本文链接:https://www.haomeiwen.com/subject/qcuxbftx.html