我正在收集有关用户的很多内容。内容的ownerID与我提供给所有者的ID不同。我也有一个ownerId到我的内部ID的映射。 如果我只用一个查询或两个查询插入内容,就会产生冲突。
测试架构:
CREATE TABLE map (
internalId INT NOT NULL,
ownerId INT NOT NULL,
PRIMARY KEY (internalId),
INDEX (ownerId)
);
Create Table content (
internalId INT NOT NULL,
contentId INT NOT NULL,
PRIMARY KEY (internalId, contentId)
);
INSERT INTO map (internalId, ownerId) VALUES (1,100), (2,1000)
选项1:从地图中选择相关行,然后构建一个插入查询。 选项2:以下查询有效(通过编程生成带有UNION ALL的内部select语句):
INSERT IGNORE INTO content (SELECT internalId, contentId FROM (SELECT 101 AS contentId, 100 AS ownerId UNION ALL
SELECT 102 AS contentId, 100 AS ownerId UNION ALL
SELECT 103 AS contentId, 100 AS ownerId UNION ALL
SELECT 1001 AS contentId, 1000 AS ownerId) AS s_q
INNER JOIN map USING (ownerId));
第二个选项要快一些(单查询和全部查询),但是我没有做任何压力测试,因此不确定如何处理由于插入或更新而导致第二个表被锁定的情况。 第一个选项更易于阅读和调试(处理死锁-您只需要事先对数据进行排序。我不知道第二个选项在这方面是否有保证)。 还有其他我没注意到的方面吗?
答案 0 :(得分:0)
使用单个查询。
原因不是“性能”,“简单性”或“风格”(尽管单个查询在所有方面都占优势)...这是数据完整性。
如果您使用2个查询,则它们之间必然存在一定的时间间隔,在此间隔内另一个进程可能会以一种方式修改数据,使您编写的更新不再包含数据库新状态的正确值。
单个查询始终具有正确的效果。
您可以启动事务,锁定所有涉及的表,读取,编写更新查询,执行更新,提交,但这对开发人员和数据库都是沉重的负担。