【问题标题】:Retrieve a unique identifier from MySQL从 MySQL 检索唯一标识符
【发布时间】: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


【解决方案1】:

您不需要 2 个查询。

解决方法很简单:

UPDATE table1 SET counter = counter+1 WHERE contract_type = 'A';

你可以和fiddle一起玩

【讨论】:

    【解决方案2】:

    我回答我自己的问题。在并发环境中在 MysSQL 中生成唯一标识符的任务可以通过 2 种方式完成:

    1) 使用带有事务和 SELECT FOR UPDATE 锁定模式的 InnoDB 表:

    START TRANSACTION (or set autocommit to 0);     
    SELECT COUNTER FROM mytable WHERE contract_type = 'A' FOR UPDATE;
    UPDATE mytable SET COUNTER = COUNTER + 1 WHERE contract_type = 'A';     
    COMMIT;
    

    SELECT ... FOR UPDATE 读取最新的可用数据,在它读取的每一行上设置排他锁。

    2) 单次访问表:

     UPDATE myTable SET COUNTER = LAST_INSERT_ID(COUNTER + 1) WHERE contract_type = 'A';
     SELECT LAST_INSERT_ID();
    

    这里的方式是 SELECT 语句仅检索标识符信息(特定于当前连接)。它不访问任何表!

    来源: http://dev.mysql.com/doc/refman/5.5/en/innodb-locking-reads.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-12
      • 2013-03-10
      • 2010-11-01
      • 2013-04-13
      • 2023-03-17
      • 2014-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多