插件数据迁移三大坑:建表冲突、版本回滚和残留表处理

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
插件开发 10 浏览 1 回复

最近重构老插件时踩遍了数据迁移的坑,总结几个高频问题:

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操作,避免出现半吊子状态。

评论1
回复 · 1
晚晴
晚晴 新手 · #1 ·
已解决,谢谢楼主
微信客服 微信客服