【问题标题】:Un-committed database transactions and auto-increment columns未提交的数据库事务和自增列
【发布时间】:2010-11-26 20:40:56
【问题描述】:

我今天遇到了一些奇怪的行为,想知道这是预期的还是标准的。我们正在对 MySQL5 使用 Hibernate。在编码过程中我忘记关闭交易,我想其他人可以联系。

当我最终关闭事务、运行代码并检查表时,我注意到以下内容。我一直错误地运行我的代码而没有关闭事务,因此没有导致插入实际的行,但是增加了自动增量代理主键值,所以我有一个间隙(即没有 id 字段值的行751 到 762)。

这是预期的还是标准的行为?可能会因数据库而异?和/或 Hibernate 自己的事务抽象是否对此有一些可能的影响?

【问题讨论】:

  • 我知道答案,但这仍然是一个有趣的问题!
  • 理想情况下,您的应用程序/设计不应该受到序列中任何间隙的影响 - 您永远不应该让自己陷入真正重要的情况

标签: java mysql hibernate transactions auto-increment


【解决方案1】:

是的,这是预期的。

如果你想一想:数据库还能做什么?如果您增加列,然后在同一事务中的其他插入中将其用作外键,并且当您这样做时其他人提交,那么他们将无法使用您的值。你会得到一个差距。

Oracle 等数据库中的序列的工作方式大致相同。一旦请求了一个特定的值,它是否被提交并不重要。它永远不会被重复使用。而且序列也不是绝对有序的。

【讨论】:

    【解决方案2】:

    这几乎是预期的行为。如果没有它,数据库将不得不等待每个插入记录的事务完成,然后再为下一个插入分配一个新的 id。

    【讨论】:

      【解决方案3】:

      是的,这是预期的行为。 This documentation 解释得很好。

      从 5.1.22 开始,实际上有三种不同的锁定模式来控制并发事务如何获取自增值。但是这三个都会导致回滚事务的间隙(回滚事务使用的自动增量值将被丢弃)。

      【讨论】:

        【解决方案4】:

        数据库序列不保证id序列没有间隙。它们被设计为独立于事务的,只有这样才能是非阻塞的。

        你想要没有间隙,你必须编写自己的存储过程来事务性地增加列,但是这样的代码会阻塞其他事务,所以你必须小心。

        您执行 SELECT CURRVAL FROM SEQUENCE_TABLE WHERE TYPE = :YOUR_SEQ_NAME FOR UPDATE; UPDATE SEQUENCE_TABLE SET CURRVAL = :INCREMENTED_CURRVAL WHERE TYPE = :YOUR_SEQ。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多