pt-osc改表过程中的中文乱码问题
//
下午使用pt-osc工具对线上表进行变更的时候,发现了一个问题,在对latin1字符集进行变更的时候,变更完毕之后的表的中文注释都变成了'?',无法正常显示了。于是在测试环境上进行了实验。
mysql> show create table latin_test1\G
*************************** 1. row ***************************
Table: latin_test1
Create Table: CREATE TABLE `latin_test1` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL COMMENT '任务名称',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
# pt指令
pt-online-schema-change --user=dba_admin --password=xxxxxxxx -h127.0.0.1 -P4306 --alter " ADD index idx_name(name) " D=yeyz,t=latin_test1 --alter-foreign-keys-method=auto --recursion-method=none --print --charset=latin1 --execute
首先创建一张字符集为latin1的表,它包含id和name两个字段,然后对这个表的name字段添加索引,变更的pt指令如上文,其中:
--charset=latin1
当我们变更完成之后,发现变更的新表内容变成:
mysql> show create table latin_test1\G
*************************** 1. row ***************************
Table: latin_test1
Create Table: CREATE TABLE `latin_test1` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL COMMENT '????',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
可以看到,comment的值变成了'????',而不是我们之前的任务名称。
出现这个情况之后,我重新做了一个测试,在pt工具的指令中,将--charset参数改成了utf8,pt指令如下:
pt-online-schema-change --user=dba_admin --password=xxxxxxx -h127.0.0.1 -P4306 --alter " modify name varchar(10) DEFAULT NULL COMMENT '任务名称' " D=yeyz,t=latin_test1 --alter-foreign-keys-method=auto --recursion-method=none --print --charset=utf8 --execute
执行完成之后,结果如下:
mysql> show create table latin_test1\G
*************************** 1. row ***************************
Table: latin_test1
Create Table: CREATE TABLE `latin_test1` (
`id` int(11) NOT NULL,
`name` varchar(10) DEFAULT NULL COMMENT '任务名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
这个结果中,我们可以看到2点:
1、我们的表latin_test1的字符集仍旧是latin1,而没有被改成utf8的字符集
2、表中的中文注释已经可以显示了。
--charset这个参数在pt-osc这个工具中,指的是使用哪种字符集去连接数据库,如果使用utf8的话,那么在连接到数据库之后,会首先执行set names utf8;它指定了客户端和服务器之间传递字符的编码规则为UTF8。如果我们使用latin1这个字符集,则说明pt-osc工具和mysql交互的字符集是latin1,而这个字符集是无法保存汉字的,所以结果中就出现了????的字眼。
除此之外,今天还专门看了下pt-osc工具创建的三个触发器的内容,触发器的内容不是单纯的将主库上的动作原封不动的搬迁到从库上,它的创建规则如下:
(1)对于DELETE操作,pt工具使用DELETE IGNORE在新表进行删除,当新有数据时,我们才进行操作,也就是说,当在后续导入过程中,如果删除的这个数据还未导入到新表,那么我们可以不在新表执行操作,因为在以后的导入过程中,原表中改行数据已经被删除,已经没有数据,那么这条记录也就不会导入到新表中; (2)对于INSERT操作,所有的INSERT INTO全部转换为REPLACE INTO,当有新数据插入到原表时,如果触发器还未把原表数据同步到新表,而这条数据已经被pt工具导入到新表了,再次insert就会发生报错,那么我们就可以利用replace into进行覆盖,这样数据也是一致的 (3)对于UPDATE操作,所有的UPDATE也转换为REPLACE INTO,因为当更新的数据的行还未同步到新表时,新表是不存在这条记录的,直接update肯定会报错,那么我们就只能插入该条数据,如果已经同步到新表了,那么也可以进行覆盖插入,所有数据与原表也是一致的;