MYSQL:发票号码的最佳解决方案

问题描述 投票:0回答:1

我正在尝试找出最好的、干净的、安全的(对于竞争条件)解决方案来处理每年从 1 重新开始的发票计数。 所以我们有一个增量数字,每年从 1 开始。

这里是我想到的解决方案,但请添加新的解决方案并解释您使用或最喜欢哪一个,以及原因。

  1. SELECT MAX(number) + 1
    在带有 INSERT 的事务中。 对于竞赛条件来说不安全,但最常用。

  2. 触发+独特索引: 在 INSERT 之前触发,将

    SELECT MAX(number) + 1
    INSERT
    发送到数据库,编号为 NULL。全部由 UNIQUE 索引包围以避免重复数字。 重复是安全的,但在竞争条件下我们会有一个例外。

  3. 边桌“柜台”。 包含字段的边表:类型、年份、last_number。 在交易中您可以执行

    SELECT last_number FROM counters WHERE year = ... AND type = ... FOR UPDATE
    。然后执行插入,并更新(如果为 0 则插入)计数器行。承诺解锁该行。 您可以将其与 UNIQUE 索引和 TRIGGER 结合起来以获得更多自动化。 我认为它更安全,但可能会导致死锁或大规模插入的性能问题。我认为边桌也不是那么干净。

  4. 触发+重试。 与第 2 点的解决方案相同,但代码中的重试机制(使用一段时间)会在“1062 - 无重复错误”失败时重新尝试查询。因此,插入之前触发器将在每次尝试时计算一个新数字。 也许是最安全的,但也许是脏代码。

  5. ???还有什么吗?

您使用什么以及您最喜欢哪一个?

mysql database sequence increment invoice
1个回答
0
投票

假设还有一些其他列,我们可以从中导出基于 1 的序列,那么我选择使用

ROW_NUMBER() OVER (ORDER BY other_col)
,假设您使用的是 MySQL 8+。具体来说,您将在查询报告时生成序列列,而不是在实际插入期间。时间戳列可以具有微秒精度,这可以确保单独的发票始终具有唯一的时间戳。

© www.soinside.com 2019 - 2024. All rights reserved.