如何使用SELECT ... FOR UPDATE用于尚不存在的记录

时间:2015-11-12 07:43:59

标签: mysql database

假设我有一个表MYTABLE有两列

SERIALNUMBER, USERNAME(其中SERIALNUMBER是独一无二的)

多个连接可能会尝试使用相同的USERNAME更新SERIALNUMBER(假设为1)。

所以我发出查询:

SELECT USERNAME FROM MYTABLE WHERE SERIALNUMBER = 1 FOR UPDATE

如果此查询返回行(表示记录已经存在),我将发布更新

UPDATE MYTABLE SET USERNAME= <different name by each connection> WHERE SERIALNUMBER = 1

否则(记录尚不存在)我发出插入

INSERT INTO MYTABLE (SERIALNUMBER, USERNAME) VALUES ( 1, <different name by each connection>)

最后我发出

COMMIT

预期行为:

在查询中持有相同SERIALNUMBER的连接应在SELECT.. FOR UPDATE语句处等待。

  1. 如果记录已存在,则每个连接应逐个更新SERIALNUMBER

  2. 如果记录不存在,则第一次连接被授予SERIALNUMBER保持锁定(因为SERIALNUMBER尚不存在,如果没有错误,则为空位锁定){{1}新记录和后续连接,因为他们可以访问锁定应该找到记录已经存在。所以他们应INSERT现有记录。

  3. 实际行为:

    1. 如果记录已存在,则按预期工作,每个连接更新记录及其UPDATE

    2. 如果记录尚不存在,则所有连接会同时继续尝试USERNAME新记录。其中,一个成功,剩下的就是例外。不同隔离级别的例外情况有所不同。

    3. 对于INSERT(这是InnoDB的默认值),它是:

        

      MySQL错误代码:1213,SQLState:40001,#ERR:找到死锁时   试图锁定;尝试重新启动交易

      对于REPEATABLE READ,它是:

        

      MySQL错误代码:1062,SQLState:23000,#ERR:重复条目“1”   关键'SERIALNUMBER'

      问题陈述:

      我想知道如何防止连接同时尝试为相同的字段值创建新记录(同时我希望只要字段值不同就允许并发记录创建)

0 个答案:

没有答案