pt-table-checksum使用dsn方式连接检测从库 问题 原因 dsn是什么

转载:https://tyoung.me/2016/09/use_dsn_method_to_connect_and_check_replicas_when_using_pt-table-checksum/

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

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)。

原因

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

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包含从库的各个连接参数(user、password、port等),由逗号分隔的多个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的参数值时,必须包含D和t选项;或者只包含t选项,同时DSN表指定数据库前缀(如percona.dsns)。

DSN表结构如下:

CREATE TABLE dsns (
id int(11) NOT NULL AUTO_INCREMENT,
parent_id int(11) DEFAULT NULL,
dsn varchar(255) NOT NULL,
PRIMARY KEY (id)
);
存储在表中的DSNs以id值排序,但是这里可以忽略id和parent_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的方式,解决测试环境在数据校验时无法连接从库的问题。

在主库新建DSN表

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

GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON . TO pt_table_check2@'192.168.0.%' IDENTIFIED BY 'checksum123';
将从库的DSN信息写入DSN表

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

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、无法检测到从库的复制延迟状态,造成从库复制延迟过大。