在同一个表中管理多个渐进数字

时间:2014-07-23 13:47:59

标签: mysql

我有一个这样的表来管理多用户应用程序中收据的累进号码的生成:

ID                 | Int(11) Auto increment, primary
Progressive_number | Int(11)
External_ID        | Int(11)

渐进式必须相对于External_ID quee,External_ID表示对外部表的主ID的引用。 例如:

ID | Prog | ExtID
1  | 1    | 1
2  | 2    | 1
3  | 1    | 2
4  | 3    | 1
5  | 4    | 1
6  | 2    | 2

到目前为止很容易,但问题是渐进式数字在quee中必须是唯一的,并且许多用户可以在同一时间生成它

我的第一个尝试是阅读最后一个Progressive,然后插入增量,如下所示:

SELECT MAX(Progressive_number) FROM table WHERE External_id = 2

但是从一些压力测试来看,在我执行连续的INSERT查询之前,其他一些人可以读取相同的值然后执行相同的INSERT,所以我最终得到两个具有相同渐进数的收据

我尝试过嵌套查询

INSERT INTO table (Progressive_number, External_ID) 
VALUES(
    (SELECT MAX(Progressive_number) FROM table WHERE External_id = 2) + 1, 
1)

我有更少的重复项,但对于这种应用程序来说,一个副本太多了。

有一种方法可以将生成完全卸载到mysql服务器,以确保任何数字都是唯一的吗?

2 个答案:

答案 0 :(得分:2)

您是否尝试在读写操作期间锁定表?

LOCK TABLES table WRITE;
INSERT INTO table (Progressive_number, External_ID) 
VALUES(
    (SELECT MAX(Progressive_number) FROM table WHERE External_id = 2) + 1, 
1)
;
UNLOCK TABLES;

(另见LOCK TABLES上的文档:http://dev.mysql.com/doc/refman/5.1/en/ansi-diff-transactions.html

答案 1 :(得分:2)

您还可以在每个INSERT的交易中执行以下操作:

获取命名锁定,应该比表锁更快:

SELECT GET_LOCK('table_insert_external_id_2', 30); 

where' table_insert_external_id_2'是一个特定的命名锁,30是以秒为单位的超时;如果select返回0,则退出。

执行插入:

INSERT INTO table (Progressive_number, External_ID) 
VALUES((SELECT MAX(Progressive_number) FROM table WHERE External_id=2)+1,1)

释放命名锁:

SELECT RELEASE_LOCK('table_insert_external_id_2');

这样,其他进程可以正常地与表进行交互。

MORE INFO