我有一个这样的表来管理多用户应用程序中收据的累进号码的生成:
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服务器,以确保任何数字都是唯一的吗?
答案 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');
这样,其他进程可以正常地与表进行交互。