防止和延迟并发mysql插入

时间:2014-04-17 09:57:28

标签: php mysql unique

我正在尝试创建一个订购系统,并创建一个唯一的序列号来区分订单,它一直运行良好,直到有一次订单同时(差异只是几秒钟) ,大约10秒钟,然后唯一的序列号变得相同(序列号从db中的最后一个序列号开始增加) 我根据某种格式创建了id,并且必须每月重置一次,因此我无法使用uniqid()。

你们对此有什么想法吗?我读到了一些数据库锁定,但是当我尝试这个解决方案"Can we lock tables while executing a query in Zend-Db"时,它也没有用。

--- --- EDIT

格式为

项目编号 - 本月订单数量

这个月的订单数是从0001到9999开始的4位数 在9999之后,它将从A001 ... A999 B001 ...... ZZZZ再次开始

这是列
| order_id | varchar(17)| utf8_general_ci |没有| PRI |

我希望现在能让它变得更加清晰:)

谢谢!

2 个答案:

答案 0 :(得分:2)

我主要考虑使用AUTO_INCREMENT主键 - 有关详细信息,请参阅manual

如果您无法使用InnoDB,则应该能够在Transaction中创建订单。在您的应用程序中,您可以检测是否存在重复项,并根据需要重新发出新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。当然,如果你在触发器中运行它,你就不需要重新填充整个表格。

答案 1 :(得分:0)

似乎我们必须使用Serializable锁定事务。在事务完成之前,它将阻止从其他会话读取和写入。

请在这里查看

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

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