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');