【发布时间】:2018-05-09 12:52:55
【问题描述】:
我们有一个使用 Oracle 数据库的 Java 系统。我以前有过使用 Laravel 的经验,我真的很喜欢它的迁移脚本的想法,并希望在我们的系统中实现类似的东西(但现在没有迁移回滚支持)。
基本上,这将基于一个 migrations 表,其中包含特定迁移脚本的唯一名称以及插入事件的日期(仅用于管理目的)。每个迁移脚本都将基于一个包含包装代码的模板,用于首先检查其名称是否存在于migrations 表中,如果找到该名称则跳过该脚本。在成功执行结束时,脚本将其名称插入到migrations 表中。
我是 Oracle 的新手,我对正确实施此功能有疑问。
我需要在单独的事务中执行每个迁移脚本,并安全地回滚整个迁移(包括架构更改),以防万一发生故障。
单个 SQL 文件将包含多个迁移脚本。
我不想重新发明轮子 - 也许这已经完成并且在 Github 或 Gist 中存在代码片段?不过我没找到。
这是我想转换成 Oracle 兼容 SQL 的伪代码:
START TRANSACTION
SET @SCRIPT_NAME = 'myUniqueMigrationScript'
IF NOT EXISTS (SELECT 1 FROM migrations WHERE migrations.name = @SCRIPT_NAME)
BEGIN
TRY
BEGIN
-- the migration itself - create/update/insert records, modify schema etc.
INSERT INTO migrations VALUES (name, created_at) VALUES (@SCRIPT_NAME, CURRENT_TIMESTAMP)
COMMIT TRANSACTION
END
CATCH error
BEGIN
ROLLBACK TRANSACTION
PRINT 'Error while executing migration ' + @SCRIPT_NAME + ': ' + error.message
END
ELSE
BEGIN
PRINT 'Skipping migration ' + @SCRIPT_NAME + ' - it had been already applied.'
END
-- possibly other similar wrapped script pieces follow in the same file
这在 Oracle 中是否可行?有哪些可能的注意事项?
我在 Microsoft SQL Server 上看到过类似的情况,它对正确的异常处理和回滚有很多警告(GO 语句的正确顺序、BEGIN CATCH、IF @@TRANCOUNT、set xact_abort 的不安全行为、@@ERROR 等。特定的句法元素)。
我想避免处理 Oracle 的这些细微差别 - 我相信 Oracle 专家从一开始就知道如何做到这一点。
【问题讨论】:
-
并回滚整个迁移如果迁移脚本包含 DDL 语句是不可能的,因为将执行隐式提交
-
检查这个flywaydb.org。对我来说,它是管理数据库迁移的最强大的框架
-
@oreh 哦,这几乎是一个交易破坏者。但如果其他部分按预期工作,也许仍然可以忍受。