如何处理独特的“伪序”。在数据库中多个进程?
我正在使用Sqlalchemy Orm和Oracle数据库使用Python 3.10。
数据定义无法更改(要求)。
我有一个具有独特约束和“伪序列”的字段,这意味着该领域是唯一的,它由以下形式组成:Year-2000 + sequence-number。
示例是220001、220002、220003等。它必须严格增加而没有空白。
目前,我们将这样的字段设置为这样(假设一年不会改变):
WHILE True
SELECT max(sequence)
Add 1 to the current maximum from above
INSERT new record with this updated value in DB.
IF Success or counter > max_tries: break
ELSE counter = counter + 1
自然存在种族条件,因为我们的网络服务器运行了多个进程(不是线程)(也是要求)。
现在,我们尝试“乐观地”多次插入值,这意味着,如果另一个记录在同一时间同时再次尝试上述“算法”。如果将来我们获得更多的流量,那么这不会比许多重试相比,这并不是那么良好的重点,而DB负载则增加。
有其他方式而不是以中等费用的乐观锁定?
I am using Python 3.10 with the SQLAlchemy ORM and an Oracle Database.
The data definition cannot be changed (requirement).
I have a field with a unique constraint and a "pseudo-sequence", which means that the field is unique and it consists of a number in following form: Year - 2000 + sequence-number.
Examples are 220001, 220002, 220003, etc. It must strictly be increasing without gaps.
For now we set this field like this (assume year does not change):
WHILE True
SELECT max(sequence)
Add 1 to the current maximum from above
INSERT new record with this updated value in DB.
IF Success or counter > max_tries: break
ELSE counter = counter + 1
Naturally there is a race condition because our webserver runs multiple processes (not threads) (also a requirement).
Right now we try to insert the value multiple times "optimistically", which means, if another record has written the number in the mean time we try the above "algorithm" again. This does not scale that good respecitvely if we get much more traffic in the future, than many retries are necessary and the DB load increases.
Is there another way instead of this optimistic locking with moderate expense?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
[tl; dr]只需使用普通序列,如果要生成伪序列,则可以计算出出于显示目的。
如果您有一个带有列的表:
注意:
Identity
列可从Oracle 12. 获得,则您有一个增量序列(您可以用作主键,并且用于任何参考约束)和日期列。
您可以使用
row_number()
分析函数和算术来生成伪序列( display 目的,而不是作为参考约束)伪序值,然后您可以使用:
但是,鉴于
id
列将依次增加,然后这是不必要的,并且pseudo_seq
列只能动态生成。db<>>
[TL;DR] Just use a normal sequence and if you want to generate the pseudo-sequence then you can calculate if for display purposes.
If you have a table with the columns:
Note:
IDENTITY
columns are available from Oracle 12.Then you have an incrementing sequence (that you can use as the primary key and for any referential constraints) and a date column.
You can generate your pseudo-sequence (for display purposes, rather than as a referential constraint) using the
ROW_NUMBER()
analytic function and arithmetic:If you did want to persist the pseudo-sequence values then you can use:
However, given that the
id
column will be increasing sequentially then that is not necessary and thepseudo_seq
column can just be dynamically generated.db<>fiddle here