pt-osc报表不存在的问题

  1. 云栖社区>
  2. 博客>
  3. 正文

pt-osc报表不存在的问题

sun_ashe 2019-07-13 10:11:44 浏览219
展开阅读全文

问题简介

在使用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;
            }
     }

网友评论

登录后评论
0/500
评论
sun_ashe
+ 关注