pt-table-checksum使用dsn方式连接检测从库

问题场景

系统环境

测试环境:

  • OS: CentOS 7
  • DB Version: MariaDB 10.0.23
  • PT Version: pt-table-checksum 2.2.18
  • 主从环境
    • Master: 192.168.0.17:53309
    • Slave: 192.168.0.18:3309

问题

在使用pt-table-checksum配置主从校验的时候,本地和生产环境都可以正常校验,而在测试环境校验的时候,却输出以下警告信息:

1
2
Cannot connect to h=192.168.0.18,p=...,u=pt_table_check
Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.

pt-table-checksum无法连接从库。
由于没有发现从库,数据校验时无法实时检测从库与主库的数据是否一致(DIFFS列始终为0),需要通过--recursion-method选项指定其他的方式来搜索、连接从库(此处--recursion-method使用的是默认值processlist,hosts)。

原因

执行的详细命令及输出如下:

1
2
3
4
5
6
shell> ./bin/pt-table-checksum --socket=/var/lib/mysql/mysql.sock --user=pt_table_check --password='checksum123' --tables=road_to_dba.test1 --replicate=percona_schema.checksums --no-check-binlog-format --no-check-replication-filters
Cannot connect to h=192.168.0.18,p=...,u=pt_table_check
Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
09-21T20:57:37      0      0      972       1       0   0.033 road_to_dba.test1

虽然在校验时pt-table-checksum没有连接到从库,但校验能够在主库正常运行,而且能够通过复制传递到从库。校验完成后,在从库也可以通过checksums表查询到数据校验不一致的表信息。

本着严(qiang)谨(po)的(zheng)态度,决定还是对于上述警告信息彻底解决掉。经过分析,具体原因如下

  • 默认情况下,pt-table-checksum使用的从库连接参数,是从主库的连接参数继承而来的,包括用户名(--user)、密码(--password)、端口(--port)等。
  • 在本次校验中,没有显式指定从库的用户名(--slave-user),密码(--slave-password),及端口。
  • 所以,在没有显式指定从库的连接参数的情况下,默认是,主库和从库的用户名、密码、端口是相同的;但是在我的测试环境中,主从环境的端口是不同的。所以导致pt-table-checksum虽然搜索到了从库,但是无法连接从库(Cannot connect to h=192.168.0.18,p=...,u=pt_table_check),紧接着报没有发现从库的错误。

由于pt-table-checksum没有参数可以用来指定从库的端口,所以使用dsn方式来指定从库的连接信息(--recursion-method dsn=D=percona,t=dsns,h=host,P=3309,u=username,p=passwd)。

dsn是什么

首先介绍俩名词:

  • dsn方法:dsn是参数--recursion-method的一个参数值。注意是dsn,不是dns…
  • DSN:DSN,即DATA SOURCE NAME,数据源名称。DSN包含从库的各个连接参数(userpasswordport等),由逗号分隔的多个option=value字符串组成。
    如:h=host,P=3309,u=username,p=passwd

dsn方法是指将从库的DSN信息存储在表(DSN表)里,然后将该表和DSN信息赋值给dsn,作为--recursion-method的参数值。
格式如:--recursion-method dsn=D=percona,t=dsns,h=host,P=3309,u=username,p=passwd

当指定pt-table-checksum的--recursion-method参数值为dsn时,它只会连接和检测这些指定的从库。当从库的MySQL用户名、密码、端口与主库不相同时,也可以通过dsn的方式来指定。

DSN的部分选项如下:

  • D
    DSN表所在的数据库名。
  • h
    从库的host。
  • p
    小写p,从库的密码。当密码包括逗号(,)时,需要使用反斜杠转义。
  • P
    大写P,从库的端口。
  • S
    连接使用的socket文件。
  • t
    存储DSN信息的DSN表名。
  • u
    从库的MySQL用户名。

每一个选项和其值的形式为option=value=的前后不能空格,如果选项值有空格,则必须使用引号引起来。

将DSN作为--recursion-method的参数值时,必须包含Dt选项;或者只包含t选项,同时DSN表指定数据库前缀(如percona.dsns)。

DSN表结构如下:

1
2
3
4
5
6
CREATE TABLE `dsns` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `parent_id` int(11DEFAULT NULL,
  `dsn` varchar(255NOT NULL,
  PRIMARY KEY (`id`)
);

存储在表中的DSNs以id值排序,但是这里可以忽略idparent_id列,只需将从库的DSN信息存储在dsn列即可。存储的DSN格式如前面在命令行上指定DSN一样,如:h=host,P=3309,u=username,p=passwd

DSN的详细介绍可参考Percona官方文档:https://www.percona.com/doc/percona-toolkit/2.2/dsn_data_source_name_specifications.html

解决问题

上面绕的有点晕。。。其实只需要知道如何使用dsn指定从库连接信息即可。

下面通过指定--recursion-method为dsn的方式,解决测试环境在数据校验时无法连接从库的问题。

  1. 在主库新建DSN表

    1
    2
    3
    4
    5
    6
      CREATE TABLE `percona_schema.dsns` (
        `id` int(11NOT NULL AUTO_INCREMENT,
        `parent_id` int(11DEFAULT NULL,
        `dsn` varchar(255NOT NULL,
        PRIMARY KEY (`id`)
      );
  2. 这里为了测试,和主库的MySQL账号区分开,新建了一个账号pt_table_check2专用于连接从库
    主库账号是pt_table_check

    1
      GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO [email protected]'192.168.0.%' IDENTIFIED BY 'checksum123';
  3. 将从库的DSN信息写入DSN表

    1
      INSERT INTO percona_schema.dsns(dsn) VALUES ("h=192.168.0.18,P=3309,u=pt_table_check2,p=checksum123");
  4. 在主库使用dsn方式,重新运行pt-table-checksum进行校验

    1
    2
    3
    4
      shell> ./bin/pt-table-checksum --socket=/var/lib/mysql/mysql.sock --user=pt_table_check --password='checksum123' --tables=road_to_dba.test1 --replicate=percona_schema.checksums --no-check-binlog-format --no-check-replication-filters --recursion-method dsn=t=percona_schema.dsns,h=192.168.0.18,P=3309,u=pt_table_check2,p=checksum123
      
                   TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
      09-21T21:22:30      0      1      972       1       0   0.273 road_to_dba.test1

从第4步可以看到,pt-table-checksum已经能够检测到从库,并且检测到主从数据不一致(DIFFS = 1)。
问题解决。

无法连接/检测从库的影响

虽然在使用pt-table-checksum时,如果无法连接/检测到从库,仍可以完成主从一致性校验。但是,这样可能会产生一些其他的问题,如下:

  1. pt-table-checksum在执行校验时,无法实时检测主从的数据是否一致。即,输出的DIFFS列始终为0。
  2. 无法检测到从库是否有使用复制过滤,可能会造成从库复制卡住。
  3. 当某个表在主库上作为一个分块进行校验时,无法检测其在从库的数据量,当该表在从库的数据量很大时,会造成从库负载过高。
  4. 无法检测到从库的复制延迟状态,造成从库复制延迟过大。