postgresql - INSERT INTO .. SELECT 导致可能的竞争条件?
问题描述
INSERT INTO A
SELECT * FROM B WHERE timestamp > (SELECT max(timestamp) FROM A);
或者,写得不同:
WITH selection AS
(SELECT * FROM B WHERE timestamp > (SELECT max(timestamp) FROM A))
INSERT INTO A SELECT * FROM selection;
如果这些查询同时运行多次,我是否可能会在 A 中得到重复的行?
Postgres 如何处理这些查询?是一个还是多个?
如果是多个查询(find max(timestamp)[1], select[2] then insert[3])我可以想象这会导致重复的行。
如果这是正确的,将其包装在 BEGIN/END(事务)中会有所帮助吗?
解决方案
是的,这可能会导致重复值。
一条语句在该语句开始的时间点看到所有表中数据的一致视图。
将单个语句包装到事务中不会改变这一点(单个语句始终作为原子语句执行,无论涉及的子查询数量如何)。
该语句将永远不会看到来自其他事务的未提交数据(这是您最终会出现重复值的根本原因)。
避免重复值的唯一安全方法是在该列上创建唯一约束(或索引)。在这种情况下,如果这样的值已经存在,则 INSERT 将导致错误。
如果要避免错误,请使用insert ... on conflict
推荐阅读
- reactjs - 你如何给material-ui抽屉组件一个可切换的主题?
- python - 是否可以在 Pandas 数据透视表中将整数转换为时间间隔?
- javascript - 无法在 React 中显示来自 SVGSVGElement 的 SVG
- spring-boot - 缺少 @PathVariable 返回 404 Not Found
- django - Django模型在两列/字段之间选择?
- reactjs - 如何使用 GO + REACT 在浏览器中保存 cookie?
- python - 在 vs 代码中安装了 pylint 扩展,但它没有识别错误
- angular - 离子无法分配给对象'[object Object]'的只读属性'property'
- javascript - 如何使图像在左右上下键上移动?
- jenkins - Jenkins 最新更新 2.277.3 LTS 后,Jenkins 电子邮件扩展插件无法正常工作