插件数据迁移三大坑:建表冲突、版本回滚和残留表处理
最近重构老插件时踩遍了数据迁移的坑,总结几个高频问题:
1. 建表IF NOT EXISTS的隐藏雷区
你以为加了IF NOT EXISTS就万事大吉?在集群环境下可能出现:
CREATE TABLE IF NOT EXISTS `plugin_foo` (
`id` int(10) NOT NULL AUTO_INCREMENT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
当两个节点同时执行时,可能一个节点用utf8mb4建表,另一个用latin1建表,最终字符集以先执行的为准。保险做法是在安装脚本显式删除旧表:
DROP TABLE IF EXISTS `plugin_foo`;
CREATE TABLE `plugin_foo` (...);
2. 版本回滚时的降级脚本
很多人只写升级SQL忘了写降级SQL,导致插件卸载时数据表变僵尸。建议每个版本升级同时准备逆向操作:
-- upgrade_v2.1.0.sql
ALTER TABLE `plugin_foo` ADD COLUMN `new_field` varchar(255);
-- downgrade_v2.1.0.sql
ALTER TABLE `plugin_foo` DROP COLUMN `new_field`;
3. 卸载时的数据残留问题
直接DROP TABLE可能引发外键约束报错,推荐采用三级删除策略:
// 先删关联数据
DELETE FROM `user_meta` WHERE `meta_key` LIKE 'plugin_foo_%';
// 再解除约束
ALTER TABLE `plugin_foo_items` DROP FOREIGN KEY `fk_user_id`;
// 最后删表
DROP TABLE IF EXISTS `plugin_foo`,`plugin_foo_items`;
建议在插件生命周期里实现install/upgrade/uninstall三个方法,用事务包裹所有SQL操作,避免出现半吊子状态。
最新打赏

