【发布时间】:2015-03-03 15:57:41
【问题描述】:
我有一个 Web 应用程序(MySQL 上的 JSP/Tomcat),它提供了填写在线合同的功能,并且需要在最后向客户端返回一个唯一的计数器或标识符作为合同协议。如果两个客户端同时确认表单,则 db 上的 SELECT MAX(COUNTER) 不能防止标识符冲突。
我有一个表格,用于跟踪每种合同类型的客户可用的下一个标识符:
CONTRACT_TYPE COUNTER
A 21
B 13
获取下一个标识符的方法是:
public int getNewCounter(String contractType) {
query1 = SELECT (COUNTER + 1) AS NEW_COUNTER from mytable WHERE CONTRACT_TYPE = 'A'
query2 = UPDATE mytable SET COUNTER = <counter_returned_on_previous> WHERE CONTRACT_TYPE = 'A'
return NEW_COUNTER;
}
这有一个问题,如果并发客户端在同一时刻提交表单,他们可能会收到相同的标识符,这是我想避免的。
换句话说,有 2 个并发客户端可能会发生这种情况:
client1-query1
client1-query2
client2-query1
client2-query2
这是正确的行为,但我也可以这样做:
client1-query1
client2-query1
client1-query2
client2-query2
导致标识符值冲突。允许多个客户端对上述两个查询进行某种“独占访问”以保证函数返回唯一标识符的最佳方法是什么?
非常感谢!
【问题讨论】:
-
UPDATE mytable SET counter = counter+1 WHERE contract_type = 'A' -
唯一的 COUNTER 分配给每个客户端? 为什么计数器应该是唯一的?
-
因为counter rapresents合约上的协议号
-
那你为什么叫列
counter而不是protocol_number? -
之所以得名,是因为它从 1 开始,像一个计数器一样去 ahed。顺便说一句,我认为您的第一个解决方案存在一些问题,因为在 UPDATE 之后应用程序需要读取该值,并且只有一个客户端应该在下一次更新之前执行此操作。我在 MySQL 中找到了一个名为 SELECT ... LOCK IN SHARE MODE 的选项,但我不知道这是不是最好的方法。
标签: mysql jdbc concurrency unique counter