Php 避免在插入手动递增的收据编号时发生冲突
我有一个查询,每次用户购买时,都会从Php 避免在插入手动递增的收据编号时发生冲突,php,mysql,sql,deadlock,database-deadlocks,Php,Mysql,Sql,Deadlock,Database Deadlocks,我有一个查询,每次用户购买时,都会从收据表中获取当前最高的收据\u计数器编号,以便创建新收据收据计数器在表中不唯一,因为它每年重置 receipt\u counter只是一个整数,用于生成类似于“pos\u id”-“receipt\u counter”的receipt\u标签 人们有可能在同一销售点同时购买产品(pos\u id) 获取新的收据\u计数器的函数如下所示: SELECT (MAX(receipt_counter) + 1) as next_receipt_counter FROM
收据
表中获取当前最高的收据\u计数器
编号,以便创建新收据<代码>收据计数器在表中不唯一,因为它每年重置
receipt\u counter
只是一个整数,用于生成类似于“pos\u id”-“receipt\u counter”
的receipt\u标签
人们有可能在同一销售点同时购买产品(pos\u id
)
获取新的收据\u计数器的函数如下所示:
SELECT (MAX(receipt_counter) + 1) as next_receipt_counter FROM receipts
问题是,当多人同时购买产品时,会触发生成新收据(以及收据编号),有时会发生冲突(多人获得相同的收据编号),因为检索收据计数器和将新收据插入数据库之间存在延迟
有没有处理此类问题的最佳实践?我是否需要使用某种死锁,或者我最初的想法有缺陷,我需要一起改变生成收据计数器的策略
编辑:收据计数器需要是一个无间隙的序列号。您可以仅为id创建单独的表,并在该id列上启用自动增量。然后分两步添加回执-首先将新记录添加到id表中,以接收回生成的id。然后使用收到的id添加实际回执。然后,当您需要用id截断表时,您需要重置增量计数器。收货计数器是否需要是一个不断增加的数字且没有间隙
如果一个有间隙的大数字可以增加,那么在当前日期/时间之外生成一个数字怎么样?如果下降到毫秒或纳秒,发生碰撞的可能性很低
例如:
2013-11-13 13:08:15.012
->1113130815012
(我省略了年份,因为你说数字每年都会重置)
在检索收据计数器和将新收据插入数据库之间有一些延迟
您可以更改软件,以便在不创建实际收据的情况下更改或检索ID,它会创建收据(具有“挂起”状态或类似的内容),然后检索其ID。在您当前创建收据的那一刻,您只需将其状态设置为“活动”或其他
这样做可以消除获取ID和存储记录之间的时间间隔,在我看来,这是问题的主要根源。您不能使用序列生成收据\u计数器吗
?如果延迟很小,可以使用锁表。然后其他用户脚本将等待您解锁该表,即订单将写入数据库。不要尝试自己实现序列生成器,让数据库来实现。请参阅Lolo:s的答案。它需要一个无间隙的递增数字。这解决了我的冲突问题,但另一个问题是,当其中一个同步事务失败时,它将在我的收据\u计数器中留下一个“间隙”