zoukankan      html  css  js  c++  java
  • Mysql: pt-table-checksum 和 pt-table-sync 检查主从一致性,实验过程

     

    一、安装 percona 包

    1.安装仓库的包

    https://www.percona.com/doc/percona-repo-config/yum-repo.html

    sudo yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
    如果成功将看下如下信息
    [root@node1 ~]# sudo yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
    Loaded plugins: fastestmirror
    percona-release-0.1-4.noarch.rpm                                      | 6.4 kB  00:00:00     
    Examining /var/tmp/yum-root-NKCxiN/percona-release-0.1-4.noarch.rpm: percona-release-0.1-4.noarch
    Marking /var/tmp/yum-root-NKCxiN/percona-release-0.1-4.noarch.rpm to be installed
    Resolving Dependencies
    --> Running transaction check
    ---> Package percona-release.noarch 0:0.1-4 will be installed
    --> Finished Dependency Resolution
     
    Dependencies Resolved
     
    =============================================================================================
    Package               Arch         Version        Repository                           Size
    =============================================================================================
    Installing:
    percona-release       noarch       0.1-4          /percona-release-0.1-4.noarch       5.8 k
     
    Transaction Summary
    =============================================================================================
    Install  1 Package
     
    Total size: 5.8 k
    Installed size: 5.8 k
    Is this ok [y/d/N]: y
    Downloading packages:
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : percona-release-0.1-4.noarch                                              1/1
      Verifying  : percona-release-0.1-4.noarch                                              1/1
     
    Installed:
      percona-release.noarch 0:0.1-4                                                             
     
    Complete!
     

    2.确保 Percona 的包是可用的

     
    sudo yum list | grep percona-toolkit
    如果执行成功会看到
    percona-toolkit.noarch                     2.2.20-1               percona-release-noarch
    percona-toolkit.x86_64                     3.0.9-1.el7            percona-release-x86_64
    percona-toolkit-debuginfo.x86_64           3.0.9-1.el7            percona-release-x86_64

    3. 安装 Percona Toolkit 工具包

     
    sudo yum install percona-toolkit
    出现如下信息表示安装成功
    Installed:
      percona-toolkit.x86_64 0:3.0.9-1.el7                                                       
     
    Dependency Installed:
      perl-Compress-Raw-Bzip2.x86_64 0:2.061-3.el7  perl-Compress-Raw-Zlib.x86_64 1:2.061-4.el7
      perl-DBD-MySQL.x86_64 0:4.023-5.el7           perl-DBI.x86_64 0:1.627-4.el7               
      perl-Data-Dumper.x86_64 0:2.145-3.el7         perl-Digest.noarch 0:1.17-245.el7           
      perl-Digest-MD5.x86_64 0:2.52-3.el7           perl-IO-Compress.noarch 0:2.061-2.el7       
      perl-IO-Socket-IP.noarch 0:0.21-4.el7         perl-IO-Socket-SSL.noarch 0:1.94-6.el7      
      perl-Net-Daemon.noarch 0:0.48-5.el7           perl-Net-LibIDN.x86_64 0:0.12-15.el7        
      perl-Net-SSLeay.x86_64 0:1.55-6.el7           perl-PlRPC.noarch 0:0.2020-14.el7           
     
    Complete!

    安装了很多命令

    pt-align                  pt-ioprofile              pt-slave-delay
    pt-archiver               pt-kill                   pt-slave-find
    pt-config-diff            pt-mext                   pt-slave-restart
    pt-deadlock-logger        pt-mongodb-query-digest   pt-stalk
    pt-diskstats              pt-mongodb-summary        pt-summary
    pt-duplicate-key-checker  pt-mysql-summary          pt-table-checksum
    pt-fifo-split             pt-online-schema-change   pt-table-sync
    pt-find                   pt-pmp                    pt-table-usage
    pt-fingerprint            pt-query-digest           pt-upgrade
    pt-fk-error-logger        pt-secure-collect         pt-variable-advisor
    pt-heartbeat              pt-show-grants            pt-visual-explain
    pt-index-usage            pt-sift                   ptx
     
     
    有的32个命令,可以分为7大类
     
     
    工具类别
    工具命令
    工具作用
    备注
    开发类
    pt-duplicate-key-checker
    列出并删除重复的索引和外键
     
    pt-online-schema-change
    在线修改表结构
     
    pt-query-advisor
    分析查询语句,并给出建议,有bug
    已废弃
    pt-show-grants
    规范化和打印权限
     
    pt-upgrade
    在多个服务器上执行查询,并比较不同
     
    性能类
    pt-index-usage
    分析日志中索引使用情况,并出报告
     
    pt-pmp
    为查询结果跟踪,并汇总跟踪结果
     
    pt-visual-explain
    格式化执行计划
     
    pt-table-usage
    分析日志中查询并分析表使用情况
    pt 2.2新增命令
    配置类
    pt-config-diff
    比较配置文件和参数
     
    pt-mysql-summary
    对mysql配置和status进行汇总
     
    pt-variable-advisor
    分析参数,并提出建议
     
    监控类
    pt-deadlock-logger
    提取和记录mysql死锁信息
     
    pt-fk-error-logger
    提取和记录外键信息
     
    pt-mext
    并行查看status样本信息
     
    pt-query-digest
    分析查询日志,并产生报告
    常用命令
    pt-trend
    按照时间段读取slow日志信息
    已废弃
    复制类
    pt-heartbeat
    监控mysql复制延迟
     
    pt-slave-delay
    设定从落后主的时间
     
    pt-slave-find
    查找和打印所有mysql复制层级关系
     
    pt-slave-restart
    监控salve错误,并尝试重启salve
     
    pt-table-checksum
    校验主从复制一致性
     
    pt-table-sync
    高效同步表数据
     
    系统类
    pt-diskstats
    查看系统磁盘状态
     
    pt-fifo-split
    模拟切割文件并输出
     
    pt-summary
    收集和显示系统概况
     
    pt-stalk
    出现问题时,收集诊断数据
     
    pt-sift
    浏览由pt-stalk创建的文件
    pt 2.2新增命令
    pt-ioprofile
    查询进程IO并打印一个IO活动表
    pt 2.2新增命令
    实用类
    pt-archiver
    将表数据归档到另一个表或文件中
     
    pt-find
    查找表并执行命令
     
    pt-kill
    Kill掉符合条件的sql
    常用命令
    pt-align
    对齐其他工具的输出
    pt 2.2新增命令
    pt-fingerprint
    将查询转成密文
    pt 2.2新增命令
     
    这次我们主要用这两个命令  pt-table-checksum 和  pt-table-sync
     
      pt-table-checksum 是 Percona-Toolkit 的组件之一,用于检测MySQL主、从库的数据是否一致。其原理是在主库执行基于statement的sql语句来生成主库数据块的checksum,把相同的sql语句传递到从库执行,并在从库上计算相同数据块的checksum,最后,比较主从库上相同数据块的checksum值,由此判断主从数据是否一致。检测过程根据唯一索引将表按row切分为块(chunk),以为单位计算,可以避免锁表。检测时会自动判断复制延迟、 master的负载, 超过阀值后会自动将检测暂停,减小对线上服务的影响。
      pt-table-checksum 默认情况下可以应对绝大部分场景,官方说,即使上千个库、上万亿的行,它依然可以很好的工作,这源自于设计很简单,一次检查一个表,不需要太多的内存和多余的操作;必要时,pt-table-checksum 会根据服务器负载动态改变 chunk 大小,减少从库的延迟。
      为了减少对数据库的干预,pt-table-checksum还会自动侦测并连接到从库,当然如果失败,可以指定--recursion-method选项来告诉从库在哪里。它的易用性还体现在,复制若有延迟,在从库 checksum 会暂停直到赶上主库的计算时间点(也通过选项--设定一个可容忍的延迟最大值,超过这个值也认为不一致)。
     
    为了保证主数据库服务的安全,该工具实现了许多保护措施:
    1. 自动设置 innodb_lock_wait_timeout 为1s,避免引起
    2. 默认当数据库有25个以上的并发查询时,pt-table-checksum会暂停。可以设置 --max-load 选项来设置这个阀值
    3. 当用 Ctrl+C 停止任务后,工具会正常的完成当前 chunk 检测,下次使用 --resume 选项启动可以恢复继续下一个 chunk
     

    工作过程

    1. 连接到主库:pt工具连接到主库,然后自动发现主库的所有从库。默认采用show full processlist来查找从库,但是这只有在主从实例端口相同的情况下才有效。
    3. 查找主库或者从库是否有复制过滤规则:这是为了安全而默认检查的选项。你可以关闭这个检查,但是这可能导致checksum的sql语句要么不会同步到从库,要么到了从库发现从库没有要被checksum的表,这都会导致从库同步卡库。
    5. 开始获取表,一个个的计算。
    6. 如果是表的第一个chunk,那么chunk-size一般为1000;如果不是表的第一个chunk,那么采用19步中分析出的结果。
    7. 检查表结构,进行数据类型转换等,生成checksum的sql语句。
    8. 根据表上的索引和数据的分布,选择最合适的split表的方法。
    9. 开始checksum表。
    10. 默认在chunk一个表之前,先删除上次这个表相关的计算结果。除非–resume。
    14. 根据explain的结果,判断chunk的size是否超过了你定义的chunk-size的上限。如果超过了,为了不影响线上性能,这个chunk将被忽略。
    15. 把要checksum的行加上for update锁,并计算。
    17-18. 把计算结果存储到master_crc master_count列中。
    19. 调整下一个chunk的大小。
    20. 等待从库追上主库。如果没有延迟备份的从库在运行,最好检查所有的从库,如果发现延迟最大的从库延迟超过max-lag秒,pt工具在这里将暂停。
    21. 如果发现主库的max-load超过某个阈值,pt工具在这里将暂停。
    22. 继续下一个chunk,直到这个table被chunk完毕。
    23-24. 等待从库执行完checksum,便于生成汇总的统计结果。每个表汇总并统计一次。
    25-26. 循环每个表,直到结束。
     
    校验结束后,在每个从库上,执行如下的sql语句即可看到是否有主从不一致发生:
     
    select * from percona.checksums where master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc) G
     
    检查使用的mysql用户一般是没有 create table 权限的,所以你可能需要先手动创建:
     
    CREATE DATABASE IF NOT EXISTS percona;
    CREATE TABLE IF NOT EXISTS percona.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;
    

      

    二、具体实验过程:

    修复 Mysql 数据库不一致及 1032 错误

    主库 node1 192.168.112.128 3306 root 123456
    从库 node2 192.168.112.131 3306 root 123456
     
    先做mysql的主从,过程略
     
    数据库操作语句主要用到如下:
     
    建库
    create database school;
    use school;
    建表
    CREATE TABLE `students` (
      `SID` tinyint(4) NOT NULL AUTO_INCREMENT,
      `Name` varchar(50) NOT NULL,
      `Age` tinyint(4) NOT NULL,
      `Gender` enum('M','F') NOT NULL,
      `Mobile` char(11) NOT NULL,
      `Address` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`SID`),
      UNIQUE KEY `Name` (`Name`),
      UNIQUE KEY `Name_2` (`Name`),
      UNIQUE KEY `index_name` (`Name`),
      KEY `Mobile` (`Mobile`)
    ) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=latin1;
     
    插入数据
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w1',41,'F',1111111,'doagnagv');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w2',42,'F',2222222,'dagongws');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w3',43,'F',3333333,'doagdnga');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w4',44,'F',4444444,'dvzxonga');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w5',45,'F',5555555,'dozgngas');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w6',46,'F',6666666,'dagongzg');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w7',47,'F',7777777,'vsdgdong');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w8',48,'F',8888888,'vsdgdong');
    INSERT INTO students (Name, Age, Gender, Mobile, Address) VALUES ('w9',49,'F',9999999,'vsgagaga'); 
     
    更新
    UPDATE students SET age = 43 WHERE Name = 'w3';
    删除
    DELETE FROM students WHERE Name = 'w4';
    

    开始实验可以看到主从是正常的状态

    现在开始搞事情,将从库的一条数据删除:

     
    可以看到主从数据已经不一样了,现在咱们来检测下主从的一致性。
     
    [root@node1 ~]# pt-table-checksum h='192.168.112.128',u='root',p='123456',P=3306 -d school --recursion-method=processlist --nocheck-replication-filters --replicate=percona.checksums --no-check-binlog-format --ignore-databases=mysql  --engines=innodb
    Checking if all tables can be checksummed ...
    Starting checksum ...
                TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
    05-08T14:26:45      0      0        9       1       0   0.030 school.students
    • TS :完成检查的时间戳。
    • ERRORS :检查时候发生错误和警告的数量。
    • DIFFS :不一致的chunk数量。当指定 --no-replicate-check 即检查完但不立即输出结果时,会一直为0;当指定 --replicate-check-only 即不检查只从checksums表中计算crc32,且只显示不一致的信息(毕竟输出的大部分应该是一致的,容易造成干扰)。
    • ROWS :比对的表行数。
    • CHUNKS :被划分到表中的块的数目。
    • SKIPPED :由于错误或警告或过大,则跳过块的数目。
    • TIME :执行的时间。
    • TABLE :被检查的表名
     
    但是并没有看到 DIFFS 这个值是 1,暂时先跳过这个未解决的问题
     
    官网给的解释如下
    " The number of chunks that differ from the master on one or more replicas. If --no-replicate-check is specified, this column will always have zeros. If --replicate-check-only is specified, then only tables with differences are printed."  
     
    那我们用恢复的命令来预同步检查一下
    [root@node1 ~]# pt-table-sync --print --sync-to-master h=192.168.112.131,u=root,p='123456',P=3306 --verbose --wait=10 --transaction --engines=innodb -d school --tables=students --recursion-method=processlist --check-triggers --foreign-key-checks -unique-checks --charset=utf8mb4

    从返回的结果来看已经发现了被我们删掉的语句,此时将 命令种的 --print 换成 --execute即可同步过去
     
    执行完同步之后我们去查看看一致性是否恢复
     
    已经恢复过来。
     
    我们继续搞事情 将从库的 w4数据删除,然后update主库的这条数据看一下
     
    先看主从状态是否正常
     
    然后
    从库执行==>   mysql> DELETE FROM students WHERE Name = 'w4';
    主库执行==>   mysql> UPDATE students SET age = 54 WHERE Name = 'w4'; 将原来的 44 换成 54
     
    可以看到主库的数据更改了,从库没有该条数据,
    并且主从也断开了
     

    【ERROR】1032:删除或更新数据,从库找不到记录

     
    先解决主从问题 ,让它恢复正常
    mysql> stop slave;
    Query OK, 0 rows affected, 1 warning (0.00 sec)
     
    mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000017', MASTER_LOG_POS=62376;
    Query OK, 0 rows affected (0.01 sec)
     
    mysql> start slave;
    Query OK, 0 rows affected (0.00 sec)
     
    或者用
     
    mysql> stop slave;
    mysql> set global sql_slave_skip_counter=1;
    mysql> start slave;
    

      

    然后我们再次对主库的这条数据修改
    主库执行==>   mysql> UPDATE students SET age = 64 WHERE Name = 'w4'; 将原来修改过的 54 换成 64
     

    主从又出现了这个问题

     
    去主库看下这个binlog文件到底发生了什么操作
    记录下 end_log_pos ,根据pos值,找到那条数据,进行insert插入
     
    mysql> show binlog events in 'mysql-bin.000017' from 62696  limit 10;
    +------------------+-------+------------+-----------+-------------+-----------------------+
    | Log_name         | Pos   | Event_type | Server_id | End_log_pos | Info                  |
    +------------------+-------+------------+-----------+-------------+-----------------------+
    | mysql-bin.000017 | 62696 | Xid        |         1 |       62727 | COMMIT /* xid=3230 */ |
    +------------------+-------+------------+-----------+-------------+-----------------------+
    1 row in set (0.00 sec)
     
    没看出来,还是直接用percona 的工具吧
     
    这个问题是由于主从状态不是两个 YES 导致的,那我们先跳过对应的错误,恢复主从
     
    如果update的行数过多可能会执行很多次 CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000017', MASTER_LOG_POS=62376; 这种操作,很影响效率,
    在这直接用 set global sql_slave_skip_counter=1; 这个命令可以一次跳过很多
     
    接着执行percona 的语句
    [root@node1 lyj]# pt-table-checksum h='192.168.112.128',u='root',p='123456',P=3306 -d schooursion-method=processlist --nocheck-replication-filters --replicate=percona.checksums --no-inlog-format --ignore-databases=mysql  --engines=innodb
    Checking if all tables can be checksummed ...
    Starting checksum ...
                TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
    05-08T15:06:11      0      0        9       1       0   0.021 school.students
    
    [root@node1 lyj]# pt-table-sync --execute --sync-to-master h=192.168.112.131,u=root,p='123456',P=3306 --verbose --wait=10 --transaction --engines=innodb -d school --tables=students --recursion-method=processlist --check-triggers --foreign-key-checks -unique-checks --charset=utf8mb4
    # Syncing A=utf8mb4,P=3306,h=192.168.112.131,p=...,u=root
    # DELETE REPLACE INSERT UPDATE ALGORITHM START    END      EXIT DATABASE.TABLE
    #      0       1      0      0 Chunk     15:06:23 15:06:23 2    school.students
     
    可以看到数据已经恢复过来了。
     
    常见错误:
    1. Diffs cannot be detected because no slaves were found
                不能自动找到从库,确认processlist或host或dsns方式用对了。
             2. Waiting for the --replicate table to replicate to XXX
                问题出在 percona.checksums 表在从库不存在,根本原因是没有从主库同步过来,所以看一下从库是否延迟严重。
    1. Pausing because Threads_running=25
                反复打印出类似上面停止检查的信息。这是因为当前数据库正在运行的线程数大于默认25,pt-table-checksum 为了减少对库的压力暂停检查了。等数据库压力过了就好了,或者也可以直接 Ctrl+C 终端,下一次加上--resume继续执行,或者加大--max-load=值。
        
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Python爬取微博热搜榜,将数据存入数据库
    Python爬取网站文章数据并存到数据库
    在自己的框架系统中使用tp类
    conda环境下pip install 无法安装到指定conda环境中(conda环境的默认pip安装位置)
    jupyter notebook 加入conda虚拟环境(指定conda虚拟环境)
    本地打包好的项目如何运行在docker中
    测试
    SQL Server创建dblink跨库查询
    深入浅析BIO、NIO、AIO
    JavaWeb_html_js_css_javaweb
  • 原文地址:https://www.cnblogs.com/liyongjian5179/p/9008890.html
Copyright © 2011-2022 走看看