简体   繁体   English

未提交的数据库事务和自动增量列

[英]Un-committed database transactions and auto-increment columns

I encountered some curious behavior today and was wondering if it is expected or standard. 我今天遇到了一些奇怪的行为,并想知道它是否是预期的或标准的。 We are using Hibernate against MySQL5. 我们正在使用Hibernate来对抗MySQL5。 During the course of coding I forgot to close a transaction, I presume others can relate. 在编码过程中我忘了关闭交易,我认为其他人可以联系。

When I finally closed the transaction, ran the code and checked the table, I noticed the following. 当我最终关闭事务时,运行代码并检查表,我注意到以下内容。 All the times I mistakenly ran my code without closing the transaction, which therefore did not result in actual rows being inserted, nevertheless incremented the auto-increment surrogate primary key value, so that I have a gap (ie no rows with id field value of 751 to 762). 我一直错误地运行我的代码而没有关闭事务,因此没有导致插入实际行,但是增加了自动增量代理主键值,因此我有一个间隙(即没有id字段值为751至762)。

Is this expected or standard behavior? 这是预期的还是标准的行为? Might it vary depending on the database? 它可能因数据库而异吗? And/or does Hibernate's own transaction abstraction have some possible effect on this? 和/或Hibernate自己的事务抽象是否会对此产生一些可能的影响?

Yes that's expected. 是的,这是预期的。

If you think about it: what else can the database do? 如果你考虑一下:数据库还能做什么? If you increment the column and then use that as a foreign key in other inserts within the same transaction and while you're doing that someone else commits then they can't use your value. 如果您增加列,然后将其用作同一事务中其他插入的外键,并且当您正在执行其他人提交时,则他们无法使用您的值。 You'll get a gap. 你会得到一个差距。

Sequences in databases like Oracle work much the same way. 像Oracle这样的数据库中的序列工作方式大致相同。 Once a particular value is requested, whether or not it's then committed doesn't matter. 一旦请求了特定值,它是否随后被提交无关紧要。 It'll never be reused. 它永远不会被重用。 And sequences are loosely not absolutely ordered too. 并且序列也不是绝对有序的。

It's pretty much expected behaviour. 这是非常期待的行为。 With out it the db would have to wait for each transaction that has inserted a record to complete before assigning a new id to the next insert. 如果没有它,db必须等待已经插入记录的每个事务完成,然后再将新id分配给下一个插入。

Yes, this is expected behaviour. 是的,这是预期的行为。 This documentation explains it very well. 该文档非常好地解释了它。

Beginning with 5.1.22, there are actually three different lock modes that control how concurrent transactions get auto-increment values. 从5.1.22开始,实际上有三种不同的锁定模式可以控制并发事务如何获得自动增量值。 But all three will cause gaps for rolled-back transactions (auto-increment values used by the rolled-back transaction will be thrown away). 但是这三个都会导致回滚事务的间隙(回滚事务使用的自动增量值将被丢弃)。

Database sequences are not to guarantee id sequence without gaps. 数据库序列不保证id序列没有间隙。 They are designed to be transaction-independent, only in such way can be non-blocking. 它们被设计为与事务无关,只有这样才能是非阻塞的。

You want no gaps, you must write your own stored procedure to increase column transactionally, but such code will block other transactions, so you must be carrefull. 您不需要间隙,您必须编写自己的存储过程以在事务上增加列,但这样的代码将阻止其他事务,因此您必须是carrefull。

You do SELECT CURRVAL FROM SEQUENCE_TABLE WHERE TYPE = :YOUR_SEQ_NAME FOR UPDATE; 你从SEQUENCE_TABLE中选择CURRVAL WHERE TYPE =:YOUR_SEQ_NAME FOR UPDATE; UPDATE SEQUENCE_TABLE SET CURRVAL = :INCREMENTED_CURRVAL WHERE TYPE = :YOUR_SEQ. UPDATE SEQUENCE_TABLE SET CURRVAL =:INCREMENTED_CURRVAL TYERE TYPE =:YOUR_SEQ。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM