pt-table-checksum和pt-table-sync用法

percona-toolkit工具包安装命令如下:

安装命令

tar xzvf percona-toolkit-2.1.1.tar.gz

cd percona-toolkit-2.1.1

perl Makefile.PL

make

make install

安装时遇到问题:


Warning: prerequisite DBD::mysql 3 not found.
Warning: prerequisite DBI 1.46 not found.
Writing Makefile for percona-toolkit
Writing MYMETA.yml

解决方法如下:

apt-get install libdbi-perl
cpan
install DBD::mysql
install DBD::mysql 3

 

pt-table-checksum使用较为简单,

基本例子:

一主两从

主:192.168.11.103:3306

从1:192.168.11.64:3306

从2:192.168.11.64:3307

命令如下:

pt-table-checksum --nocheck-replication-filters --databases=test --replicate=test.checksums --host=192.168.11.103 --port 3306 -uchecksums -p123456 --no-check-binlog-format
pt-table-checksum命令只需要在主机执行即可。

一、参数说明:

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

--recursion-method :指定复制检查的方式,默认情况下使用SHOW PROCESSLIST,如果非标准的3306端口,就使用SHOW SLAVE HOSTS的方式,推荐使用dsn方式,手动指定
更多的参数请见官网,上面指出来的是常用的,对该场景够用的参数。
 
执行时显示的结果:
TS            :完成检查的时间。
ERRORS        :检查时候发生错误和警告的数量。
DIFFS         :0表示一致,1表示不一致。当指定--no-replicate-check时,会一直为0,当指定--replicate-check-only会显示不同的信息。
ROWS          :表的行数。
CHUNKS        :被划分到表中的块的数目。
SKIPPED       :由于错误或警告或过大,则跳过块的数目。
TIME          :执行的时间。
TABLE         :被检查的表名。
 [object Object] [object Object] 二、checksms表简要说明
Field [object Object]Type
db [object Object]char(64)
tbl [object Object]char(64)
chunk [object Object]int(11)
chunk_time [object Object]float
chunk_index [object Object]varchar(200)
lower_boundary [object Object]text
upper_boundary [object Object]text
this_crc [object Object]char(40)
this_cnt [object Object]int(11)
master_crc [object Object]char(40)
master_cnt [object Object]int(11)
ts [object Object]timestamp
this_crc 记录本地表用crc32算法(循环冗余校验)算出的值
this_cnt 记录本地表的记录行总数
master_crc 记录Master表用crc32算法(循环冗余校验)算出的值
master_cnt 记录Master表用记录行总数
lower_boundary 记录如果本地表数据过多,对主键要分段检索,分段最小值
upper_boundary 记录如果本地表数据过多,对主键要分段检索,分段最大值
chunk 记录如果本地表数据过多,对主键要分段检索,区间范围

chunk_time 执行时长
chunk_index 索引名字
 

三、查看master的generlog,显示如下:

 23217 Query SHOW CREATE TABLE `test`.`pub_sec_code`
  23217 Query 
  23217 Query EXPLAIN SELECT * FROM `test`.`pub_sec_code` WHERE 1=1
  23217 Query USE `test`
  23217 Query DELETE FROM `test`.`checksums` WHERE db = 'test' AND tbl = 'pub_sec_code'
  23217 Query USE `test`
  23217 Query EXPLAIN SELECT COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `sec_id`, `mar_code`, `sec_full_name`, `sec_short_name`, `com_uni_code`, `sec_type_big_par`, `sec_mar_par`, `list_sta_par`, `list_sect_par`, `list_date`, `is_cont`, `isin_code`, `area_uni_code`, `chi_short_name`, `eng_name`, `eng_short_name`, `spe_short_name`, CONCAT(ISNULL(`com_uni_code`), ISNULL(`list_sta_par`), ISNULL(`list_sect_par`), ISNULL(`list_date`), ISNULL(`is_cont`), ISNULL(`isin_code`), ISNULL(`area_uni_code`), ISNULL(`chi_short_name`), ISNULL(`eng_name`), ISNULL(`eng_short_name`), ISNULL(`spe_short_name`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test`.`pub_sec_code`
  23217 Query REPLACE INTO `test`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'test', 'pub_sec_code', '1', NULL, NULL, NULL, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `sec_id`, `mar_code`, `sec_full_name`, `sec_short_name`, `com_uni_code`, `sec_type_big_par`, `sec_mar_par`, `list_sta_par`, `list_sect_par`, `list_date`, `is_cont`, `isin_code`, `area_uni_code`, `chi_short_name`, `eng_name`, `eng_short_name`, `spe_short_name`, CONCAT(ISNULL(`com_uni_code`), ISNULL(`list_sta_par`), ISNULL(`list_sect_par`), ISNULL(`list_date`), ISNULL(`is_cont`), ISNULL(`isin_code`), ISNULL(`area_uni_code`), ISNULL(`chi_short_name`), ISNULL(`eng_name`), ISNULL(`eng_short_name`), ISNULL(`spe_short_name`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test`.`pub_sec_code`
  23217 Query SHOW WARNINGS
  23217 Query SELECT this_crc, this_cnt FROM `test`.`checksums` WHERE db = 'test' AND tbl = 'pub_sec_code' AND chunk = '1'
  23217 Query UPDATE `test`.`checksums` SET chunk_time = '0.082246', master_crc = 'b152f17f', master_cnt = '21570' WHERE db = 'test' AND tbl = 'pub_sec_code' AND chunk = '1'
  23217 Query SHOW GLOBAL STATUS LIKE 'Threads_running'

master库执行replace和update语句,从机同步这些sql语句,从机也生成checksums表,通过从机的checksums表中的数据可以知道主从哪里的数据不一致。

replace语句是计算本机的this_crc
update的语句是直接更新 master_crc为master上的校验值

 

四、测试结果的要点:

1:要查询的表必须要有主键。
2:可以满足单表大数据的数据校验,遇到单表大数据时候,此软件会对主键分段检索,不会造成表的死锁。
3:主从数据库的端口不同时,也可以校验数据,只不过无法显示运行结果,需要手动去从库查看验证结果。

4: recursion-method的使用,此参数可以部分满足上面要点3的不足

在test库中建表,并插入从库的信息. 

  1. CREATE TABLE `dsns` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULTNULL, `dsn` varchar(255) NOT NULL, PRIMARY KEY (`id`) );

  2. �C 写入从库信息

  3.  

    INSERT INTO dsns (parent_id,dsn) values(1,'h=192.168.11.64,u=checksums,p=123456,P=3306');

  4. �C 如果有多个从库,就插入多条记录.

  5.  INSERT INTO dsns (parent_id,dsn) values(1,'h=192.168.11.64,u=checksums,p=123456,P=3307');

  6. 详细命令如下:

  7. pt-table-checksum --nocheck-replication-filters --replicate=test.checksums --host=192.168.11.103 --port 3306 --databases=test,test1 -uchecksums -p123456 --no-check-binlog-format --recursion-method=dsn=h=192.168.11.103,D=test,t=dsns

此处dsn指的是dsns表在192.168.11.103机器上,库是test。和上面的--databases=test,test1 无关。

5:最好在峰值低的时候执行。

6:no-check-binlog-format参数一定要启用,因为pt-table-checksum在主机其实执行的是 REPLACE INTO `test`.`checksums` 和update这类更新语句,然后从机同步执行此语句,如果binlog-format采用ROW模式,从机的checksums表数据就会和主机一样,所以必须采用statment模式,加了no-check-binlog-format这个参数后,保证

pt-table-checksum在session中用statment模式来执行。



pt-table-sync使用也比较简单,但是比pt-table-checksums复杂些。

pt-table-sync: 高效的同步MySQL表之间的数据,他可以做单向和双向同步的表数据。他可以同步单个表,也可以同步整个库。它不同步表结构、索引、或任何其他模式对象。所以在修复一致性之前需要保证他们表存在。

 

--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 :执行命令。
更多的参数请见官网,上面指出来的是常用的,对该场景够用的参数。
我的建议是使用--replicate参数和--sync-to-master
好处是:
1:使用replicate可以不用自己指定需要同步的表
2:使用sync-to-master可以不用指定master信息,
例子如下:
pt-table-sync --sync-to-master --replicate=test.checksums --charset=utf8 h=192.168.11.64,u=checksums,p=123456,P=3307 --print
再写一个不用sync-to-master和replicate的例子
例子1:pt-table-sync --replicate=test.checksums h=192.168.11.103,u=checksums,p=123456,P=3306 h=192.168.11.64,u=checksums,p=123456,P=3307 --print
例子2:pt-table-sync --sync-to-master --databases=test --tables=dic_ind --charset=utf8 h=192.168.11.64,u=checksums,p=123456,P=3307 --print
一、general log日志内容

不适用replicate参数的例子:

 a: DROP TABLE IF EXISTS `__maatkit_char_chunking_map`
      4 Query BEGIN

 CREATE TEMPORARY TABLE `test`.`__maatkit_char_chunking_map` ( `ind_uni_code` varchar(32) NOT NULL COMMENT '统一编码') ENGINE=MEMORY
     4 Query COMMIT
     4 Query BEGIN
     4 Query INSERT INTO `test`.`__maatkit_char_chunking_map` VALUES (CHAR('48'))
     4 Query COMMIT
     4 Query BEGIN
     4 Query INSERT INTO `test`.`__maatkit_char_chunking_map` VALUES (CHAR('49'))
     4 Query COMMIT
     4 Query BEGIN
     4 Query INSERT INTO `test`.`__maatkit_char_chunking_map` VALUES (CHAR('50'))

 

使用replicate参数的例子:

17 Query SHOW VARIABLES LIKE 'innodb_version'
     17 Query SELECT @@binlog_format
     17 Query 
     17 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
     16 Query SELECT db, tbl, CONCAT(db, '.', tbl) AS `table`, chunk, chunk_index, lower_boundary, upper_boundary, COALESCE(this_cnt-master_cnt, 0) AS cnt_diff, COALESCE(this_crc <> master_crc OR ISNULL(master_crc) <> ISNULL(this_crc), 0) AS crc_diff, this_cnt, master_cnt, this_crc, master_crc FROM test.checksums WHERE master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc)
     16 Query 
     16 Query USE `test`
     16 Query SHOW CREATE TABLE `test`.`dic_ind`
     16 Query 
     16 Query SELECT MIN(`ind_uni_code`), MAX(`ind_uni_code`) FROM `test`.`dic_ind` FORCE INDEX (`PRIMARY`) WHERE (((`ind_uni_code` >= '0')) AND ((`ind_uni_code` <= 'S190102')))
     16 Query EXPLAIN SELECT * FROM `test`.`dic_ind` FORCE INDEX (`PRIMARY`) WHERE ((`ind_uni_code` >= '0')) AND ((`ind_uni_code` <= 'S190102'))

两个比较可以看出不使用replicate需要创建临时表来比较两边的数据,增加了系统的负载,不利于系统。


你可能感兴趣的:(mysql,工具包)