pt-online-schema-change使用中的不当,引起的数据库不可写入问题

时间:2021-08-04 18:43:57

战战兢兢,如履薄冰

这次不是pt-online-schema-change的锅,主要责任在我。

背景

5000万行表加字段操作,数据量30G,有主键,dba是一般的操作账号,除delete,drop,gran外,其他权限全部具备。
pt命令:

pt-online-schema-change --host=127.0.0.1  --user=dba --password=     --charset=utf8  --check-interval 5 --max-lag 1  --check-replication-filters --chunk-time=0.5   --critical-load="Threads_connected=1500,Threads_running=256" --critical-load="Threads_connected=1000,Threads_running=128" --set-vars="lock_wait_timeout=10" --alter="add type tinyint(2) NOT NULL DEFAULT '1' " --tries create_triggers:1:1,drop_triggers:3:1,swap_tables:3:1 D=test,t=hb  --execute  --print

当开始执行时,dev日志报错,并且出现数据库不可写入问题,报错如下:
DELETE command denied to user ‘dba@’127.0.0.1’ for table ‘_new_hb’,此处的 _new_hb是posc 实现ddl的一种方法,具体可以百度。当收到OP反馈监控报警时,我想到是自己的操作引起的,但是不确定原因,立马停止操作,但是系统依然没有回复正常,然后删除掉了pt建立的那三个触发器,于是恢复正常。
2015最后一天,想加完这个索引,就开开心心去吃饭呢,然而自己打了脸。

原因分析

pt最关键的地方在于那三个触发器,这次出问题也是因为触发器引起的

CREATE TRIGGER `pt_osc_paygent_user_del` AFTER DELETE ON `paygent`.`user` FOR EACH ROW DELETE IGNORE FROM `paygent`.`_user_new` WHERE `paygent`.`_user_new`.`id` <=> OLD.`id`

CREATE TRIGGER `pt_osc_paygent_user_upd` AFTER UPDATE ON `paygent`.`user` FOR EACH ROW REPLACE INTO `paygent`.`_user_new` (`id`, `jdb_id`, `yft_id`, `error`, `create_time`, `update_time`, `phone`, `identity`, `name`, `balance`, `state`) VALUES (NEW.`id`, NEW.`jdb_id`, NEW.`yft_id`, NEW.`error`, NEW.`create_time`, NEW.`update_time`, NEW.`phone`, NEW.`identity`, NEW.`name`, NEW.`balance`, NEW.`state`)

CREATE TRIGGER `pt_osc_paygent_user_ins` AFTER INSERT ON `paygent`.`user` FOR EACH ROW REPLACE INTO `paygent`.`_user_new` (`id`, `jdb_id`, `yft_id`, `error`, `create_time`, `update_time`, `phone`, `identity`, `name`, `balance`, `state`) VALUES (NEW.`id`, NEW.`jdb_id`, NEW.`yft_id`, NEW.`error`, NEW.`create_time`, NEW.`update_time`, NEW.`phone`, NEW.`identity`, NEW.`name`, NEW.`balance`, NEW.`state`)

线上用户paygent对于user表update操作,会调用pt_osc_paygent_user_upd触发器去_new_user表上做delete+insert操作,然而dba用户 没有delete权限,所以此触发器不可能执行update后的操作,然后就会报出如下错误:
dev用户执行如下:
mysql> update user set state=’2’ where jdb_id=’461637096036085760’;
ERROR 1142 (42000): DELETE command denied to user ‘dba’@’127.0.0.1’ for table ‘_hb_new’(报错位置在_hb_new)
此错误信息会返回给dev用户线程,并且被研发的日志捕获。

总结

pt还是可以继续使用的,但是在使用的时候一定要使用合适的用户去操作,避免发生类似的问题,后果很严重,慎重。