gpt4 book ai didi

mysql - 如何使这两个同时发生的事务始终成功,而不会导致唯一性冲突?

转载 作者:可可西里 更新时间:2023-11-01 08:37:19 30 4
gpt4 key购买 nike

假设有一个 tags 表,其中有一个名为 name 的唯一字段。

我有一个交易,我在其中执行选择以查看是否存在具有特定名称的标签,如果不存在,我将创建它:

START TRANSACTION;
SELECT * FROM TAGS WHERE NAME = "FOO";
-- IF A TAG NAMED "FOO" DIDN'T EXIST THEN
INSERT INTO TAGS VALUES("FOO");
COMMIT;

当两个客户端以默认隔离级别(可重复读取)运行此事务时,这种交错将导致其中一个客户端因唯一性冲突而失败:

START TRANSACTION;
START TRANSACTION;
SELECT * FROM TAGS WHERE NAME = "FOO";
SELECT * FROM TAGS WHERE NAME = "FOO";
-- IF A TAG NAMED "FOO" DIDN'T EXIST THEN
INSERT INTO TAGS VALUES("FOO");
-- IF A TAG NAMED "FOO" DIDN'T EXIST THEN
INSERT INTO TAGS VALUES("FOO");
COMMIT;
COMMIT;

我想如果我将隔离级别设置为可序列化,我可以避免这种情况,但我注意到同样的交错会导致死锁。

我如何修改事务以使其永远不会因违反唯一性约束而失败?

作为记录,这是对应于此场景的 Ruby on Rails (ActiveRecord) 代码:

class Tag < ActiveRecord::Base
def self.create_tag(name)
transaction do
# setting isolation level to serializable leads to a deadlock
# Tag.connection.execute("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE")
gets
tag = Tag.find_by_name(name)
if tag.nil?
gets
Tag.create!(:name => name)
end
end
end
end

最佳答案

我不是 Rails 专家,但您可以通过使用单个查询并将 IGNORE 添加到插入中,从 SQL 的角度解决问题,如果标记已经存在,这不会失败。

INSERT IGNORE INTO TAGS VALUES("FOO");

关于mysql - 如何使这两个同时发生的事务始终成功,而不会导致唯一性冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8711647/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com