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

Azure SQL数据库唯一键约束失效,出现重复记录如何排查?

唯一键约束失效导致Azure SQL中出现重复记录的原因分析

问题背景

我们有一套运行8年以上的大型SaaS系统数据库,基于Azure SQL构建,配套Web应用也部署在Azure平台上,此前从未出现问题。今日凌晨,部分C# Web应用报表突然因检测到表中存在重复记录而失败。经核查,涉事表中确实存在违反唯一键约束的完全重复记录,请问为何唯一键在插入/更新操作时未生效?

编辑补充:涉事表结构

CREATE TABLE [tenant_clientnamehere].[tbl_cachedstock](
[clusteringkey] [bigint] IDENTITY(1,1) NOT NULL,
[islivecache] [bit] NOT NULL,
[id] [uniqueidentifier] NOT NULL,
[stocklocation_id] [uniqueidentifier] NOT NULL,
[stocklocation_referencecode] [nvarchar](50) NOT NULL,
[stocklocation_description] [nvarchar](max) NOT NULL,
[productreferencecode] [nvarchar](50) NOT NULL,
[productdescription] [nvarchar](max) NOT NULL,
[unitofmeasurename] [nvarchar](50) NOT NULL,
[targetstocklevel] [decimal](12, 3) NULL,
[minimumreplenishmentquantity] [decimal](12, 3) NULL,
[minimumstocklevel] [decimal](12, 3) NULL,
[packsize] [int] NOT NULL,
[isbuffermanageddynamically] [bit] NOT NULL,
[dbmcheckperioddays] [int] NULL,
[dbmcheckperiodbuffergroup_id] [uniqueidentifier] NULL,
[ignoredbmuntildate] [datetime2](7) NULL,
[notes1] [nvarchar](100) NOT NULL,
[notes2] [nvarchar](100) NOT NULL,
[notes3] [nvarchar](100) NOT NULL,
[notes4] [nvarchar](100) NOT NULL,
[notes5] [nvarchar](100) NOT NULL,
[notes6] [nvarchar](100) NOT NULL,
[notes7] [nvarchar](100) NOT NULL,
[notes8] [nvarchar](100) NOT NULL,
[notes9] [nvarchar](100) NOT NULL,
[notes10] [nvarchar](100) NOT NULL,
[seasonaleventreferencecode] [nvarchar](50) NULL,
[seasonaleventtargetstocklevel] [decimal](12, 3) NULL,
[isarchived] [bit] NOT NULL,
[isobsolete] [bit] NOT NULL,
[currentstocklevel] [decimal](12, 3) NULL,
[quantityenroute] [decimal](12, 3) NULL,
[recommendedreplenishmentquantity] [decimal](12, 3) NULL,
[bufferpenetrationpercentage] [int] NOT NULL,
[bufferzone] [nvarchar](10) NOT NULL,
[bufferpenetrationpercentagereplenishment] [int] NOT NULL,
[bufferzonereplenishment] [nvarchar](10) NOT NULL,


CONSTRAINT [PK_tbl_cachedstock] PRIMARY KEY CLUSTERED 
(
    [clusteringkey] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
 CONSTRAINT [UK_tbl_cachedstock_1] UNIQUE NONCLUSTERED 
(
    [islivecache] ASC,
    [id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [tenant_clientnamehere].[tbl_cachedstock] ADD  CONSTRAINT [DF__tbl_cache__isarc__1A200257]  DEFAULT ((0)) FOR [isarchived]
GO

ALTER TABLE [tenant_clientnamehere].[tbl_cachedstock] ADD  CONSTRAINT [DF__tbl_cache__isobs__1B142690]  DEFAULT ((0)) FOR [isobsolete]
GO

冲突记录详情

两条违反唯一键约束的记录键值为:

  • islivecache = 1
  • id = BA7AD2FD-EFAA-485C-A200-095626C583A3

可能的原因及排查方向

1. 约束被临时禁用或未恢复

检查是否有运维操作(如批量数据导入、表结构变更)临时禁用了唯一键约束UK_tbl_cachedstock_1,操作完成后未重新启用。执行以下查询确认约束状态:

SELECT name, is_disabled
FROM sys.indexes 
WHERE object_id = OBJECT_ID('tenant_clientnamehere.tbl_cachedstock') 
AND name = 'UK_tbl_cachedstock_1';

2. 并发竞态条件导致重复插入

如果应用采用"先查询是否存在,再插入/更新"的拆分逻辑,且未用原子操作或事务兜底,高并发场景下可能出现两个请求同时通过存在性校验,随后插入相同键值的记录。Azure SQL默认READ COMMITTED隔离级别无法完全阻止此类竞态。

核查应用代码:

  • 是否存在非原子性的插入/更新逻辑?
  • 关键操作是否包裹在事务中?
  • 是否未利用数据库唯一约束做最终兜底校验?

3. 唯一索引IGNORE_DUP_KEY参数变更

虽然当前表结构中IGNORE_DUP_KEY = OFF,但需确认近期是否有ALTER INDEX操作修改过该参数。若该参数曾被设为ON,插入重复键值时仅返回警告而非错误,会导致重复记录被插入。可通过Azure SQL审计日志查询索引历史变更。

4. 高可用同步异常

若系统使用Azure SQL异地复制、镜像或只读副本,同步过程中可能出现异常,导致主副本约束未正确同步到副本,或副本数据回写主副本时引入重复记录。检查Azure Portal中数据库同步状态,查看是否有失败的同步任务。

5. 批量数据操作绕过约束

近期若有bcp、BULK INSERT或INSERT...SELECT等批量操作,且使用了IGNORE_CONSTRAINTS或TABLOCK选项(部分场景下会临时禁用约束检查),可能导致重复记录插入。核查数据库导入/恢复日志,确认是否存在此类操作。

6. 数据库引擎版本bug(低概率)

Azure SQL特定版本可能存在唯一约束失效的已知bug。检查当前数据库版本,对比微软官方已知问题列表,确认是否有匹配的bug及对应补丁。


临时解决方案

  1. 删除重复记录,恢复报表服务:
WITH CTE AS (
    SELECT *,
           ROW_NUMBER() OVER(PARTITION BY islivecache, id ORDER BY clusteringkey) AS RowNum
    FROM tenant_clientnamehere.tbl_cachedstock
    WHERE islivecache = 1 AND id = 'BA7AD2FD-EFAA-485C-A200-095626C583A3'
)
DELETE FROM CTE WHERE RowNum > 1;
  1. 重新验证并重建唯一键约束:
ALTER INDEX UK_tbl_cachedstock_1 ON tenant_clientnamehere.tbl_cachedstock REBUILD;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:35:18