You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多实例并发下带LEFT JOIN的INSERT INTO SELECT防重失效求解

问题原因

当前跨表插入SQL在单实例下运行正常,但多实例并发调用时出现重复插入,核心原因是查询阶段没有对匹配范围加互斥锁:多个并发会话会同时读取到table2中尚未插入table1的同批次记录,各自拿到相同的结果集后执行插入,最终触发重复数据问题。

修正方案

1. 给查询语句加并发锁提示(SQL层面直接修复)

从语句使用的TOP语法判断你用的是SQL Server数据库,只需要在关联table1时加上UPDLOCK和HOLDLOCK表提示,就能保证并发场景下同批次待插入数据只会被一个会话读取到,修正后的SQL如下:

INSERT INTO table1 (col1, col2)
SELECT DISTINCT TOP 10
    t2.col1, 
    t2.col2 
FROM   
    table2 t2 
LEFT JOIN 
    table1 t1 WITH (UPDLOCK, HOLDLOCK) 
    ON t2.col1 = t1.col1 
    AND t2.col2 = t1.col2 
WHERE  
    t1.col1 IS NULL

锁提示的作用说明:

  • UPDLOCK:查询时对扫描到的匹配范围加更新锁,其余并发会话无法对同一范围数据加更新锁或排他锁,从根源避免多个会话读到同一份待插入数据
  • HOLDLOCK:将锁持有到整个事务提交后再释放,不会在查询执行完就提前放锁,保证查询+插入的全流程互斥

2. 加唯一约束做兜底强保障

必须在table1上针对(col1, col2)字段创建唯一联合约束(或唯一联合索引),这是防止重复数据的最后一道防线:哪怕锁配置异常、或者有其他路径写入数据,数据库层面会直接拒绝重复值写入,不会产生脏数据。
创建唯一约束的示例SQL:

ALTER TABLE table1
ADD CONSTRAINT uk_table1_col1_col2 UNIQUE (col1, col2)
注意事项
  • 执行上述插入SQL时建议显式开启事务,不要依赖自动提交,保证锁的生命周期符合预期
  • 批量插入的TOP值不要设置过大,避免锁范围过高影响业务并发吞吐量,可根据实际业务压测结果调整批量大小

内容的提问来源于stack exchange,提问作者Deepak Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:36:21