在开始之前,我想向@Grumbler85 道歉——你是对的。这个问题困扰了我一段时间,我会尽我所能回答这个问题。
事务和锁定都不是足够的解决方案。
原因:锁不好,因为一旦你锁定了一个表,你必须解锁它。解锁可能会失败,我们都知道一般网络和计算机的不稳定性质。底线是 - 您必须使用 C# 应用程序来发出锁定和解锁。每次生成发票时,您都必须锁定用作计数器的表,迫使所有其他 MySQL 会话等到您释放锁定。根据我的经验,几天之内,您将不得不聘请一名管理员,其工作是释放锁定。
事务还不够好,因为每个事务都对数据的快照进行操作(简化解释,可以修改事务隔离级别)。这意味着 1 笔交易可以计算出发票编号必须为 6,而另一笔交易也可以计算出发票编号必须为 6。
您可以做的是使 invoice_number 唯一,因此如果 2 个(或更多)交易尝试插入相同的编号,您将获得其中至少 1 个的例外,从而防止出现空白但无法创建发票。
使用 auto_increment 也不是一个选项。Auto_increment 只是一个简单的计数器。这意味着 auto_increment 不会“重用”由于某种原因而丢弃的数字 - 原因是发生错误并且无法保存事务,从而有效地使为该记录计算的 auto_increment 丢失。
那么有哪些选择呢?就个人而言,我会创建一个简单的服务,它会在预定义的时间间隔内运行,它会更新尚未invoice_number
设置的发票。该服务不会提供并发访问,并且总是有一个活动连接可以处理一组已插入的发票。
确实有法律(在某些国家,例如英格兰)规定必须有一个有序的发票编号,我也错了。资料来源:http ://www.hmrc.gov.uk/vat/managing/charging/vat-invoices.htm 来源摘录:
一个唯一的发票编号,它与前一张发票的编号相同——如果您损坏或取消了一张有序列号的发票,您必须保留它,以便在下次增值税检查时向增值税官员出示
最后一个选项是,如果两个或多个交易获得相同的发票编号,您对发票创建失败感到满意,这意味着您必须实施一种重新运行失败交易的方法(这很简单)。