【问题标题】:Excluding a table from a transaction rollback从事务回滚中排除表
【发布时间】:2011-05-10 20:45:37
【问题描述】:

我们有一个表和一组用于生成 pk id 的程序。表保存最后一个 id,过程获取 id,增加它,更新表,然后返回新增加的 id。

此过程可能在事务中。问题是,如果我们有回滚,它可能会回滚到在事务期间使用的任何 id 之前的 id(比如从不同的用户或线程生成)。那么当id再次递增时,会导致重复。

有没有办法从父事务中排除 id 生成表以防止这种情况发生?

添加细节我们当前的问题...

首先,我们有一个准备将大量数据迁移到其中的系统。该系统由一个 ms-sql (2008) 数据库和一个 textml 数据库组成。 sql 数据库存储不到 3 天的数据,而 textml 充当任何更早的数据的存档。 textml db 还依赖于 sql db 为特定字段提供 id。这些字段当前是 Identity PK 的,并且在发布到 texml 数据库之前在插入时生成。我们不想通过 sql 清洗所有迁移的数据,因为记录会在流量和数据方面淹没当前系统。但与此同时,我们无法生成这些 id,因为它们是 sql server 控制的自动递增值。

其次,我们有一个系统要求,需要我们能够将旧资产从 texml 数据库中提取出来,并使用原始 ID 将其插入到 sql 数据库中。这样做是为了更正和编辑,如果我们更改 id,它将破坏我们无法控制的客户端系统下游的关系。当然这都是个问题,因为 id 列是 Identity 列。

【问题讨论】:

  • 您使用的是什么关系型数据库?它是否具有内置的自动增量功能,您可以使用而不是尝试自己滚动?
  • Joe 是对的——这就是为什么大多数 RDBMS 都有内置的 Identity 类型函数。
  • 如果您有确定何时发生回滚的逻辑,您可以使用/在相同的逻辑内将表设置回原始值。
  • 不确定这是否是一个好的解决方案 - 我自己不会这样做。但是,如果您'必须做您必须做的事情',您可能希望改用 Timestamp 列(二进制),并以某种方式将其转换为 int。即使您回滚父事务,该值也不会重复。

标签: sql transactions rollback


【解决方案1】:

procedures 获取 id,增加它, 更新表,然后返回 新增加的id

这会导致死锁。过程必须在一个单一的原子步骤中递增和返回,例如。通过使用 SQL Server 中的 OUTPUT 子句:

update ids
set id = id + 1
output inserted.id
where name= @name;

您不必担心并发性。您以这种方式生成 id 的事实意味着只有一个事务可以增加一个 id,因为更新将独占锁定该行。你不能得到重复。您确实获得了所有操作的完整序列化(即没有性能和低吞吐量),但这是一个不同的问题。这就是为什么您应该使用内置机制来生成序列和身份的原因。这些特定于每个平台:MySQL 中的AUTO_INCREMENT、Oracle 中的SEQUENCE、SQL Server 中的IDENTITYSEQUENCE(仅在 Denali 中的序列)等。

更新
当我阅读您的编辑时,您想要控制生成的身份的唯一原因是能够插入回存档记录。这已经可以了,只需使用IDENTITY_INSERT

允许插入显式值 进入表的标识列

在插入旧记录时将其打开,然后再将其关闭:

SET IDENTITY_INSERT recordstable ON;
INSERT INTO recordstable (id, ...) values (@oldid, ...);
SET IDENTITY_INSERT recordstable OFF;

至于为什么手动生成的 id 会序列化所有操作:任何生成 id 的事务都会独占锁定 ids 表中的行。在第一个事务提交或回滚之前,没有其他事务可以读取或写入该行。因此,任何时候都只能有一个事务在表上生成一个 id,即。序列化。

【讨论】:

  • 这是一些很好的信息,特别是考虑到我们当前的过程不是原子的。我不确定我是否理解您提到的序列化问题。使用内置机制的问题在于,它们无法控制何时在行插入之外生成 id。我赞成您的答案,并希望将其标记为答案,但我不确定它是否真的解决了最初的问题,或者为手头的问题提供了解决方案。我还扩展了问题,为问题添加了更多细节。
  • 关闭身份插入只能解决问题的第二部分。仍然存在处理迁移的问题,以及迁移数据无需通过系统即可获得有效 id 的需求。太糟糕了,我们没有使用 denali,因为序列非常适合这个。 MS 解决方法如下所示 - blogs.msdn.com/b/sqlcat/archive/2006/04/10/….
  • 说了这么多,您的信息可以提供可靠的解决方法,非常感谢!
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多