SELECT中的Mysql死锁。。如果不存在,则插入

SELECT中的Mysql死锁。。如果不存在,则插入,mysql,transactions,deadlock,Mysql,Transactions,Deadlock,我有一个简单的分割测试表: CREATE TABLE `tracked_split_test_track_variant` (  `tracked_split_test_id` int(10) unsigned NOT NULL,  `track_id` bigint(20) unsigned NOT NULL,  `variant` char(1) NOT NULL,   PRIMARY KEY (`tracked_split_test_id`,`track_id`),  KEY

我有一个简单的分割测试表:

CREATE TABLE `tracked_split_test_track_variant` (
  `tracked_split_test_id` int(10) unsigned NOT NULL,
  `track_id` bigint(20) unsigned NOT NULL,
  `variant` char(1) NOT NULL,  
  PRIMARY KEY (`tracked_split_test_id`,`track_id`),
  KEY `tracked_split_test_track_variant_1` (`tracked_split_test_id`),
  KEY `tracked_split_test_track_variant_2` (`track_id`),
  CONSTRAINT `fk_tracked_split_test_track_variant_2` 
    FOREIGN KEY (`track_id`) 
    REFERENCES `track` (`id`)
    ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_tracked_split_test_track_variant_1` 
    FOREIGN KEY (`tracked_split_test_id`) 
    REFERENCES `tracked_split_test` (`id`) 
    ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
其中变量为a或B

当系统询问“我应该向该用户显示哪个变体?”时,我希望发生以下情况:

选择属于当前轨迹和跟踪分割测试的跟踪分割测试轨迹变体 如果不存在记录,创建一个带有随机变量的新记录并插入它 目前,我正在事务中运行SELECT和可选INSERT查询,如下所示:

    SELECT * 
      FROM tracked_split_test_track_variant
     WHERE track_id = :track_id
       AND tracked_split_test_id = :tracked_split_test_id
FOR UPDATE

我将FOR UPDATE添加到SELECT中,以便在两个事务运行时使用相同的详细信息。。我不会尝试两次插入


尽管我会尽快做出承诺,但我现在却陷入了僵局。我做错了吗?

由于元组在此事务之外是不可变的,因此我提出了使用显式命名锁的以下解决方案:

SELECT GET_LOCK('tracked_split_test_track_variant-xxx-yyy',30);

SELECT * 
  FROM tracked_split_test_track_variant
 WHERE tracked_split_test_id = :tracked_split_test_id
   AND track_id = :track_id

     [
INSERT 
  INTO tracked_split_test_track_variant
VALUES (:track_id, :tracked_split_test_id, :variant)
     ]

    DO RELEASE_LOCK('tracked_split_test_track_variant-xxx-yyy');
其中xxx是跟踪的\u分割\u测试\u id,yyy是跟踪的\u id

不过,我想看看是否有更好的解决方案

SELECT GET_LOCK('tracked_split_test_track_variant-xxx-yyy',30);

SELECT * 
  FROM tracked_split_test_track_variant
 WHERE tracked_split_test_id = :tracked_split_test_id
   AND track_id = :track_id

     [
INSERT 
  INTO tracked_split_test_track_variant
VALUES (:track_id, :tracked_split_test_id, :variant)
     ]

    DO RELEASE_LOCK('tracked_split_test_track_variant-xxx-yyy');