pt-osc报表不存在的问题解决

问题简介

pt-osc版本

ashe@macos:/data/PerconaToolkit (master) $ ./pt-online-schema-change  --version
pt-online-schema-change 2.2.20

在使用pt-osc进行在线表结构变更时,有时会报表不存在的错误,然而进入通过show create table发现表是存在的。

问题排查

pt-osc命令如下

ashe@ubuntu:~$ pt-online-schema-change --alter="add name_1 varchar(10)" \
--host=127.0.0.1 \
--user=ashe \
--port=13307 \
--password=ashe \
--charset='utf8' \
--check-interval 5 \
--max-lag 2 \
--drop-old-table \
--check-replication-filters \
--chunk-time 1 \
--critical-load='Threads_connected=1300,Threads_running=256' \
--max-load='Threads_connected=1500,Threads_running=256' \
--set-vars='lock_wait_timeout=10' \
--tries create_triggers:1:1,drop_triggers:3:1,swap_tables:3:1 \
--progress=time,5 \
--no-check-alter --execute --print D=ashe,t=ASHE

执行报错如下

ashe@ubuntu:~$ pt-online-schema-change --alter="add name_1 varchar(10)" \
> --host=127.0.0.1 \
> --user=ashe \
> --port=13307 \
> --password=ashe \
> --charset='utf8' \
> --check-interval 5 \
> --max-lag 2 \
> --drop-old-table \
> --check-replication-filters \
> --chunk-time 1 \
> --critical-load='Threads_connected=1300,Threads_running=256' \
> --max-load='Threads_connected=1500,Threads_running=256' \
> --set-vars='lock_wait_timeout=10' \
> --tries create_triggers:1:1,drop_triggers:3:1,swap_tables:3:1 \
> --progress=time,5 \
> --no-check-alter --execute --print D=ashe,t=ASHE
No slaves found.  See --recursion-method if host ubuntu has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
The original table `ashe`.`ASHE` does not exist.

通过数据库show create table

mysql> show create table ashe.ASHE\G
*************************** 1. row ***************************
       Table: ASHE
Create Table: CREATE TABLE `ashe` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=266222 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

可以看出数据库中确实存在此表。问题的关键在于pt-osc的命令中使用的是大写的表名,按理说,数据库设置的参数

lower_case_table_names=1

即便使用大写,也是没有问题的,因为数据库自动忽略大小写了。将pt-osc的命令中改成小写可以解决这个问题。但是并有没有就此停止,看了下pt-osc的perl脚本源码,找到了问题的根本所在,如下

根本原因

pt-osc在函数check_table中,通过show tables from ashe like ‘ASHE’;找到对应的目标表,

mysql> show tables from ashe like 'ASHE';
+-----------------------+
| Tables_in_ashe (ASHE) |
+-----------------------+
| ashe                  |
+-----------------------+
1 row in set (0.00 sec)

此时获取到的表名为小写的,紧接着用此表名对比命令行输入的大写ASHE,

 if ( !$row->[0] || $row->[0] ne $tbl ) {
      PTDEBUG && _d('Table does not exist');
      return 0;
   }

$row->[0] ne $tbl为区分大小写的对比,此时报错。但其实表确实存在,并且用大写访问是没有问题的。

由于目前线上环境的SQL发布已经自动化,DBA不会人工进行审核,在RD看来,数据库不区分大小写,所以提交的上线单中使用大写是没有问题的,但是却报表不存在,难以接受。

问题修复

考虑两种情况,一种是数据库区分大小写,一种是不区分大小写。
首先获取参数设置情况

 my $sql_check_lower_case_table_name = "SELECT  \@\@lower_case_table_names";
	 PTDEBUG && _d($sql_check_lower_case_table_name);
	 
	 my $row_lower_case = $dbh->selectrow_arrayref($sql_check_lower_case_table_name);

lower_case_table_names=0,区分大小写

在此时,依然按照pt-osc之前的方式,进行数据库表名的判断

	 if ( $row_lower_case->[0] eq '0' ) {
			if ( !$row->[0] || $row->[0] ne $tbl ) {
				PTDEBUG && _d('Table does not exist');
				return 0;
			}
	 }

lower_case_table_names=1,不区分大小写

在数据库不区分大小写时,字符串对比时也要忽略大小写

 if( $row_lower_case->[0] eq '1' ) {
			if ( !$row->[0] || lc($row->[0]) ne lc($tbl) ) {
				PTDEBUG && _d('Table does not exist');
				return 0;
			}
	 }

Patch file

对于不同的版本,可以酌情修改。

ashe@macos:/data/PerconaToolkit (master) $ git diff 7c23a808d9555c3e62c42e76503734f463e86fea 53c10fd3d5f4e61a3624b39bdfa22068e7fda30e
diff --git a/pt-online-schema-change b/pt-online-schema-change
index 5af900e..abc83f0 100755
--- a/pt-online-schema-change
+++ b/pt-online-schema-change
@@ -3386,10 +3386,23 @@ sub check_table {
       $self->{check_table_error} = $e;
       return 0;
    }
-   if ( !$row->[0] || $row->[0] ne $tbl ) {
-      PTDEBUG && _d('Table does not exist');
-      return 0;
-   }
+        my $sql_check_lower_case_table_name = "SELECT  \@\@lower_case_table_names";
+        PTDEBUG && _d($sql_check_lower_case_table_name);
+
+        my $row_lower_case = $dbh->selectrow_arrayref($sql_check_lower_case_table_name);
+        if ( $row_lower_case->[0] eq '0' ) {
+                       if ( !$row->[0] || $row->[0] ne $tbl ) {
+                               PTDEBUG && _d('Table does not exist');
+                               return 0;
+                       }
+        }
+
+        if( $row_lower_case->[0] eq '1' ) {
+                       if ( !$row->[0] || lc($row->[0]) ne lc($tbl) ) {
+                               PTDEBUG && _d('Table does not exist');
+                               return 0;
+                       }
+        }

    PTDEBUG && _d('Table', $db, $tbl, 'exists');
    return 1;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值