数据迁移实战:建表与版本升级时容易忽略的5个致命细节
最近在重构一个老插件时踩了不少坑,总结下数据迁移中最容易翻车的几个场景。建表SQL看着简单,但版本迭代时经常出现字段漏改、索引失效等问题:
1. 默认值陷阱 ALTER TABLE时如果没显式声明NOT NULL,老数据会被自动填充NULL而不是默认值:
// 错误示范 ALTER TABLE `plugin_orders` ADD COLUMN `payment_type` TINYINT DEFAULT 1; // 正确姿势 ALTER TABLE `plugin_orders` ADD COLUMN `payment_type` TINYINT NOT NULL DEFAULT 1;
2. 索引重建暗坑 修改字段类型时原索引不会自动重建,必须显式DROP INDEX:
ALTER TABLE `plugin_logs` CHANGE COLUMN `create_time` `create_time` INT(11) NOT NULL, DROP INDEX `idx_time`, ADD INDEX `idx_time` (`create_time`);
3. 卸载残留问题 卸载插件时记得清理自定义数据库表,但要注意保留用户数据的需求场景。建议采用标记删除模式:
// 卸载脚本示例
if (!defined('IN_UNINSTALL')) {
$db->query("DROP TABLE IF EXISTS `plugin_temp_data`");
$db->query("UPDATE `user_meta` SET `is_deleted`=1 WHERE `meta_key`='plugin_settings'");
}
4. 版本回滚预案 在upgrade.php中一定要写版本回退逻辑,特别是涉及数据迁移时:
// 版本210→220升级失败时回滚
if ($failed) {
$db->query("ALTER TABLE `plugin_items` DROP COLUMN `new_field`");
return false;
}
5. 字符集连环炸 跨版本迁移时遇到过最恶心的就是utf8mb4冲突,一定要在建表时显式声明:
CREATE TABLE `plugin_comments` ( `id` int(11) NOT NULL AUTO_INCREMENT, `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
最新打赏

