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

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

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

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

评论12
回复 · 12
RyanMoon
RyanMoon 初级星灿心语 · #12 ·
写得很清楚,收藏了
清醒的星星
清醒的星星 新手 · #11 ·
学到了,顶一下
Blake
Blake 初级赏金猎人 · #10 ·
学到了,顶一下
SunnyDay
SunnyDay 初级流金绮梦 · #9 ·
已解决,谢谢楼主
徐超悦
徐超悦 初级赏金猎人 · #8 ·
已解决,谢谢楼主
SkyWalker
SkyWalker 初级璃海华章 · #7 ·
感谢分享!
浪漫的草莓
浪漫的草莓 初级 · #6 ·
感谢分享!
发光的海盐
发光的海盐 新手流金绮梦 · #5 ·
支持了~
🐱汽水🎐
🐱汽水🎐 初级星灿心语 · #4 ·
学到了,顶一下
IrisPark
IrisPark 初级 · #3 ·
学到了,顶一下
BlakeMoon
BlakeMoon 初级 · #2 ·
已解决,谢谢楼主
晚晴
晚晴 新手 · #1 ·
已解决,谢谢楼主
微信客服 微信客服 QQ官方交流群 QQ官方交流群