Ada*_*dam 68 sql t-sql sql-server concurrency locking
我总是使用类似下面的东西来实现它:
INSERT INTO TheTable
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WHERE
PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
...但是一旦加载,就会发生主键违规.这是唯一插入此表的语句.那么这是否意味着上述陈述不是原子的?
问题是,这几乎不可能随意重建.
也许我可以将其更改为以下内容:
INSERT INTO TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT
NULL
FROM
TheTable
WITH
(HOLDLOCK,
UPDLOCK,
ROWLOCK)
WHERE
PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
虽然,也许我使用错误的锁或使用过多的锁定或其他东西.
我在stackoverflow.com上看到了其他问题,其中答案是建议"IF(SELECT COUNT(*)... INSERT"等),但我总是在(可能是不正确的)假设单个SQL语句是原子的.
有没有人有任何想法?
gbn*_*gbn 60
那么"JFDI"模式呢?
BEGIN TRY
INSERT etc
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
END CATCH
Run Code Online (Sandbox Code Playgroud)
说真的,这是最快和最没有锁定的并发,特别是在大量时.如果UPDLOCK升级并且整个表被锁定怎么办?
第4课:在调整索引之前开发upsert proc时,我首先相信该
If Exists(Select…)
行会触发任何项目并禁止重复.纳达.在短时间内有数千个重复项,因为相同的项目将在相同的毫秒内达到upsert并且两个事务都会看到不存在并执行插入.经过大量测试后,解决方案是使用唯一索引,捕获错误,然后重试允许事务查看行并执行更新而不是插入.
GSe*_*erg 23
我添加了最初不存在的HOLDLOCK.如果没有这个提示,请忽略该版本.
就我而言,这应该足够了:
INSERT INTO TheTable
SELECT
@primaryKey,
@value1,
@value2
WHERE
NOT EXISTS
(SELECT 0
FROM TheTable WITH (UPDLOCK, HOLDLOCK)
WHERE PrimaryKey = @primaryKey)
Run Code Online (Sandbox Code Playgroud)
此外,如果您确实想要更新一行(如果它存在)并插入(如果不存在),您可能会发现这个问题很有用.
Chr*_*ith 17
您可以使用MERGE:
MERGE INTO Target
USING (VALUES (@primaryKey, @value1, @value2)) Source (key, value1, value2)
ON Target.key = Source.key
WHEN MATCHED THEN
UPDATE SET value1 = Source.value1, value2 = Source.value2
WHEN NOT MATCHED BY TARGET THEN
INSERT (Name, ReasonType) VALUES (@primaryKey, @value1, @value2)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
32895 次 |
最近记录: |