我最近尝试过2个数据库的大合并。我们将数据库2中的模式重新创建到数据库1中,并创建了一个脚本,将数据库2中的所有数据传输到数据库1中。此脚本运行大约需要35分钟,并使用以下内容进行事务处理:
BEGIN TRANSACTION
...
IF(@@error<>0)
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
完整脚本有点敏感,但这里有一些具有相同结构的SQL:http://pastebin.com/GWJ3ZnkF
我们运行了脚本,所有数据都没有错误地传输。我们测试了使用新组合数据库运行的系统(删除了对旧数据库的访问权限)。
但作为最后一项任务,我们希望将旧数据库脱机以确保没有人使用该数据库。为此,我们使用了:
ALTER DATABASE <dbname> SET OFFLINE WITH ROLLBACK IMMEDIATE
这很糟糕。在这行SQL代码之后,我们刚刚复制的组合数据库中的所有数据突然消失了。我首先认为它没有真正完成所以“回滚立即”听起来像是在我的交易上执行了回滚..
但为什么呢?交易是否已全部承诺?
此外,我尝试再次运行相同的脚本几次,但每次尝试都没有复制数据,即使它说脚本成功了。我不知道为什么......它是否记得我的离线回滚?
我的关系真的发生了什么?
答案 0 :(得分:1)
听起来你有一个未提交的待处理事务,你强迫它回滚,失去了一些工作。其余部分通过脚本的结构来解释。您的脚本不可能从头到尾只有一个事务。只回滚了最后一个事务,因此数据库现在处于一半被复制的状态。可能你的脚本会进行各种检查,这个中间状态会在&#39; ELSE&#39;上发送脚本。它没有做正确工作的分支(即显然什么都不做)。
没有发布确切的脚本,无论如何都是猜测。
现在您需要将数据库还原到一致状态,即数据复制之前的状态。使用您在数据移动之前所做的备份( 进行备份,对吧?)。要获得额外的功劳,请确保您的脚本为idempotent,并且可以在半更新的数据库上正常运行。
答案 1 :(得分:0)
立即使用ROLLBACK:
将回滚所有未完成的交易以及任何其他交易 与数据库的连接将是 立即断开连接。
听起来有人混淆了2个数据库,或者有未完成的交易?....你能发布整个脚本吗?
不仅要检查@@ERROR
,还要检查@@TRANCOUNT
。
答案 2 :(得分:0)
我会仔细检查以确保没有未完成的交易。要么遍历该文件并计算BEGIN TRANSACTION
vs COMMIT TRANSACTION
行的数量,要么在SELECT @@TRANCOUNT
的末尾添加一个语句,以确保没有剩余的已打开的事务。
如果您的数据已提交,则断开连接就不会丢失。