防止和延迟并发mysql插入


Preventing and delaying concurent mysql insert

我正在尝试创建一个订购系统,并创建一个唯一的序列号来区分订单,它运行良好,直到有一次在同一时间出现订单(差异仅以秒为单位,约10秒),然后唯一序列号变为相同(序列号从db中的最后一个序列号开始递增)
我正在创建基于某种格式的id,它必须每月重新播种,所以我不能使用uniqid()。

你们知道这件事吗?我读过一些数据库锁定的文章,但当我尝试这个解决方案"我们可以在Zend-db中执行查询时锁定表吗"时,它也不起作用。

---编辑---

格式为

项目编号本月订单年数

这个月的订单号是从0001到9999的4位数字9999之后,它将从A001重新开始。。。A999 B001。。。ZZZZ

这是列
|order_id|varchar(17)|utf8_general_ci|NO|PRI|

我希望这能让它现在更清楚:)

谢谢!

我主要研究使用AUTO_INCREMENT主键-有关详细信息,请参阅手册。

如果这不可能,并且您正在使用InnoDB,那么您应该能够在事务中创建订单。在您的应用程序中,您可以检测是否存在重复,并根据需要重新颁发新的ID。如果订单创建失败,使用事务将确保数据库中没有剩余数据。

根据附加信息编辑:

我会添加一个AUTO_INCREMENT主键,并使用一个单独的"OrderName"列作为所需的格式。这应该允许您执行以下操作,例如:

UPDATE orders o 
 JOIN (
  SELECT 
   year(o2.dte) y,
   month(o2.dte) m,
   min(o2.Order_ID) minid 
  FROM orders o2 GROUP BY y,m) AS t ON (t.m=month(dte) AND t.y=year(dte)) 
SET o.OrderName=CONCAT('p-n-',year(o.dte),"-",o.Order_ID-t.minid);

id列为int PRIMARY KEY AUTO_INCREMENT,将确保订单始终处于正确的顺序,并且不需要锁定。在本例中,CONCAT将指定您的订单号格式。如果愿意,可以在触发器中运行此UPDATE,以确保立即填充OrderName。当然,如果在触发器中运行此操作,则不需要重新填充整个表。

看来我们必须使用带有Serializable锁定的事务。它将阻止从其他会话读取和写入,直到事务完成。

请在此处查看

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html