SuperAPI AI 工具集

t-sql-upserts-merge

数据与分析

查看项目

更新于 10-16 00:31

技能介绍

用途:解决 upsert 的并发正确性问题。IF EXISTS ... UPDATE ELSE INSERT 与裸 MERGE 都是竞态,单会话测试通过,两个调用者同时到达即失败。

主要能力:给出三种经八并发会话验证的正确写法。一是 MERGE 加 WITH (HOLDLOCK)(提示写在目标表别名之前),且连接键必须有唯一索引,否则范围锁过宽会引发 Msg 1205 死锁;二是先 UPDATE WITH (SERIALIZABLE),@@ROWCOUNT = 0 时再 INSERT,适合行通常已存在;三是先 UPDATE,未命中时 INSERT 并捕获 2601/2627 后改为 UPDATE,适合行通常不存在。三者都依赖被 upsert 键上的唯一约束或唯一索引。

应拒绝的 MERGE 形态:带 WHEN NOT MATCHED BY SOURCE THEN DELETE 的部分批次;源可含重复键(Msg 8672);ON 子句含过滤条件;列存储目标;高并发大规模场景;频繁执行语句中的字面量(MERGE 不适用简单参数化,应经 sys.sp_executesql 传参)。MERGE 还需分号结尾,否则报 Msg 10713。

索引视图:完整性检查对索引视图只做物理检查,逻辑检查需 EXTENDED_LOGICAL_CHECKS,故视图与基表不一致时常规检查发现不了;资料称已发布的最小复现及另外四种形态在兼容级别 120 至 170 下未复现不一致,若不一致的修复是删除并重建视图聚集索引。

验证方式:用两个 shell 同时运行 upsert,比较最终值与算术总数;sqlcmd -b 出错时返回非零,-m-1 打印全部消息。示例命令:sqlcmd -S localhost,1433 -d appdb -C -b -m-1。注意 go-sqlcmd 1.x 在严重级别 10 消息上不打印 Msg 头,ODBC 版位于容器 /opt/mssql-tools18/bin/sqlcmd。

限制:不涉及重试循环设计;具体平台与认证标志变化未展开。