gh-ost
gh-ost copied to clipboard
MySQL 8 rename column lost data
hello,
From MySQL 8+ version, MySQL support rename column syntax, for example:
alter table test rename column a to b;
but gh-ost only support regexpn not include this syntax
sanitizeQuotesRegexp = regexp.MustCompile("('[^']*')")
renameColumnRegexp = regexp.MustCompile(`(?i)\bchange\s+(column\s+|)([\S]+)\s+([\S]+)\s+`)
dropColumnRegexp = regexp.MustCompile(`(?i)\bdrop\s+(column\s+|)([\S]+)$`)
renameTableRegexp = regexp.MustCompile(`(?i)\brename\s+(to|as)\s+`)
autoIncrementRegexp = regexp.MustCompile(`(?i)\bauto_increment[\s]*=[\s]*([0-9]+)`)
I do one case:
CREATE TABLE `cases_test` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' ,
`case_code` text COLLATE utf8mb4_general_ci ,
`node_id` int unsigned NOT NULL DEFAULT '0' ,
`user_id` int unsigned NOT NULL DEFAULT '0' ,
`is_delete` tinyint(1) NOT NULL DEFAULT '0' ,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
Then run ddl:
gh-ost --host=127.0.0.1 --port=3306 --user=root --password=xxxxxxx --database=auto_test --table=cases_test --alter="rename column name to _name_bak " --allow-on-master --chunk-size=5000 --max-load=Threads_connected=25000,Threads_running=100 --initially-drop-ghost-table --initially-drop-old-table --approve-renamed-columns --max-lag-millis=5000 --switch-to-rbr --nice-ratio=1 --postpone-cut-over-flag-file=/tmp/test1.file --initially-drop-socket-file=True --panic-flag-file=/tmp/test2.file --throttle-control-replicas="127.0.0.1:3307" --verbose --execute
insert copy sql is
insert /* gh-ost `auto_test`.`cases_test` */ ignore into `auto_test`.`_cases_test_gho` (`id`, `case_code`, `node_id`, `user_id`, `is_delete`, `create_time`, `update_time`)
(select `id`, `case_code`, `node_id`, `user_id`, `is_delete`, `create_time`, `update_time` from `auto_test`.`cases_test` force index (`PRIMARY`)
where (((`id` > ?) or ((`id` = ?))) and ((`id` < ?) or ((`id` = ?)))) lock in share mode
)
column "name" not in insert sql, so lost data.
I this gh-ost need add one regexp, for example:
mysql8RenameColumnRegexp = regexp.MustCompile(`(?i)\brename\s+column\s+([\S]+)\s+to\s+([\S]+)`)
and parseAlterToken add code:
func (this *AlterTableParser) parseAlterToken(alterToken string) (err error) {
allStringSubmatch = mysql8RenameColumnRegexp.FindAllStringSubmatch(alterToken, -1)
for _, submatch := range allStringSubmatch {
if unquoted, err := strconv.Unquote(submatch[1]); err == nil {
submatch[1] = unquoted
}
if unquoted, err := strconv.Unquote(submatch[2]); err == nil {
submatch[2] = unquoted
}
this.columnRenameMap[submatch[1]] = submatch[2]
}
}