TN.*_*TN. 12 t-sql sql-server transactions transaction-isolation snapshot-isolation
以下陈述:
INSERT INTO dbo.Changes([Content], [Date], [UserId], [CompanyId])
VALUES (@1, @2, @3, @4);
SELECT @@identity;
Run Code Online (Sandbox Code Playgroud)
给我这个SQL错误3960:
由于更新冲突,快照隔离事务中止.您不能使用快照隔离直接或间接访问数据库'myDatabase'中的表'dbo.Companies'来更新,删除或插入已被其他事务修改或删除的行.重试事务或更改update/delete语句的隔离级别.
据我所知,从错误消息中,我不应该dbo.Companies在另一个连接修改期间更新,删除或插入表dbo.Companies.
但是为什么当我将一个新行插入另一个表dbo.Changes(具有外键dbo.Companies)并且我没有删除引用的行时,它会发生dbo.Companies,但我只是更新行dbo.Companies而不是主键?这应该可行,不应该吗?(这是SQL Server中的错误吗?)
更新:
表如下所示:
dbo.Changes([Id] int PK, [Content] nvarchar,
[Date] datetime, [UserId] int, [CompanyId] int -> dbo.Companies.[Id])
dbo.Companies([Id] int PK, [Name] nvarchar)
Run Code Online (Sandbox Code Playgroud)
第二次更新正在做:
UPDATE dbo.Companies WHERE [Id] = @1 SET [Name] = @2;
Run Code Online (Sandbox Code Playgroud)
看来SQL Server 将获取它必须读取的任何记录的更新锁,即使它没有修改它.
有关此microsoft.public.sqlserver.server线程的更多信息:
没有CustomerContactPerson上的支持索引,声明
从ContactPerson删除WHERE ID = @ID;
将需要对CustomerContactPerson中的所有行进行"当前"读取,以确保没有引用已删除的ContactPerson行的CustomerContactPerson行.使用索引,DELETE可以确定CustomerContactPerson中没有相关行,而无需读取受其他事务影响的行.
此外,在快照事务中,用于读取要转换和更新的数据的模式是在读取时采用UPDLOCK.这可确保您根据"当前"数据进行更新,而不是"一致"(快照)数据,并且当您发出DML时,数据将不会被锁定,并且您不会无意中覆盖另一场会议的变化.
我们的修复是为外键添加索引
在您的示例中,我怀疑为Changes.CompanyId添加索引会有所帮助.我不确定这是否真的是一个解决方案.SQL Server优化器可以选择不使用索引吗?
| 归档时间: |
|
| 查看次数: |
15745 次 |
| 最近记录: |