想要加悲观锁可是数据行还不存在怎么办?

两个并发事务想要对同一个KEY的数据进行更新,但是如果这个KEY的数据行还不存在的话,那么select .. for update当然不能锁住这行记录,想当然的想到,可不可以先insert一下,然后在悲观锁呢?

那么引入了一个新的问题,如果两个并发事务同时insert的话,就会插入重复的数据,如果insert的unique key重复的话,第二个线程会报错的,有没有更优雅的方法?

答案是MySQL innodb的INSERT ... ON DUPLICATE KEY UPDATE语法;

用法见官网文档:https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

If you specify ON DUPLICATE KEY UPDATE, and a row is inserted that would cause a duplicate value in a UNIQUEindex or PRIMARY KEY, MySQL performs an UPDATE of the old row. For example, if column a is declared as UNIQUEand contains the value 1, the following two statements have similar effect:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;

使用ON DUPLICATE KEY UPDATE语法,第二条insert语句,会自动变成Update语句,而不会导致重复插入数据的BUG;

做个简单的测试:

CREATE TABLE `tcc` (
  `idx` INT(11),
  `typeid` INT(11),
  `value1` INT(11),
  `value2` INT(11),
  UNIQUE KEY(idx, typeid)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

-- 第一条SQL的执行,会新增一条数据,本SQL多次执行,效果相同,因为后续的操作,变成了UPDATE
INSERT INTO tcc (idx, typeid, value1) 
VALUES (1,2,3) ON DUPLICATE KEY UPDATE value1=3;

-- 第二条SQL直接进行UPDATE,把新列的值update进去
INSERT INTO tcc (idx, typeid, value2) 
VALUES (1,2,4) ON DUPLICATE KEY UPDATE value2=4;

产出结果只有一条:

"idx" "typeid" "value1" "value2"
"1" "2" "3" "4"

有了这个利器,那么代码中就可以直接insert.. on duplicate key update,这个SQL的执行能保证数据库中会存在记录,然后加上悲观锁,来保证不同的事务不会出现更新冲突情况;

本文地址:http://crazyant.net/1835.html

相关推荐

1 thought on “想要加悲观锁可是数据行还不存在怎么办?”

Leave a Comment