Pergunta

I'm trying to create a system for ordering and create a unique serial number to distinguish the order, it's working well until one time there is an order at same time (the difference is just in seconds, about 10 seconds) and then the unique serial number become same (the serial number is increment from the last serial number in db).
I'm creating the id based on some format and it have to be reseted per month so I can't use uniqid().

Do you guys have any idea about this? I read about some db locking but when I tried this solution "Can we lock tables while executing a query in Zend-Db" it's also didn't worked.

---EDIT---

The format is

projectnumber-year-number of order this months

the number of order this months is 4 digits started from 0001 until 9999 after 9999 it will start again from A001 ... A999 B001 ... ZZZZ

and this is the column
| order_id | varchar(17) | utf8_general_ci | NO | PRI |

I hope this make it more clear now :)

Thanks!

Foi útil?

Solução

Primarily I'd look into using AUTO_INCREMENT primary key - see manual for details.

If that's not possible and you are using InnoDB you should be able to create the order in a Transaction. In your application you can then detect if there were duplicates and re-issue a new ID as needed. Using transaction will ensure that there is no residual data left in the database if your order creation fails.

EDIT based on the additional information:

I'd add an AUTO_INCREMENT primary key and use a separate "OrderName" column for the desired format. That should allow you to do the following, for example:

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 column is int PRIMARY KEY AUTO_INCREMENT and will ensure that the orders are always in correct order and will not require locking. In this example CONCAT will dictate your order number format. You can run this UPDATE in a trigger, if you wish, to ensure that the OrderName is immediately populated. Of course if you run this in a trigger, you don't need to repopulate the whole table.

Outras dicas

Seem we must use transaction with Serializable locking. It will prevent read and write from other session until transaction complete.

Please view at here

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

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top