sql-server – 选择/插入版本的Upsert:是否有高并发的设计模式?
发布时间:2020-05-23 23:03:33 所属栏目:MsSql 来源:互联网
导读:我想做一个UPSERT的SELECT / INSERT版本.以下是现有代码的模板: // CREATE TABLE Table (RowID INT NOT NULL IDENTITY(1,1), RowValue VARCHAR(50))IF NOT EXISTS (SELECT * FROM Table WHERE RowValue = @VALUE)BEGIN INSERT Ta
|
我想做一个UPSERT的SELECT / INSERT版本.以下是现有代码的模板: // CREATE TABLE Table (RowID INT NOT NULL IDENTITY(1,1),RowValue VARCHAR(50)) IF NOT EXISTS (SELECT * FROM Table WHERE RowValue = @VALUE) BEGIN INSERT Table VALUES (@Value) SELECT @id = SCOPEIDENTITY() END ELSE SELECT @id = RowID FROM Table WHERE RowValue = @VALUE) 该查询将从许多并发会话中调用.我的性能测试表明,它将一直在特定负载下抛出主键违规. 是否有一个高并发方法,这个查询将允许它保持性能,同时仍然避免插入已经存在的数据? 解决方法您可以使用LOCKs来实现SERIALIZABLE,但这会降低并发性.为什么不先尝试共同的条件(“大多是插入或大部分选择”),然后安全处理“补救”行动?也就是说,“JFDI”模式…预计大多数INSERT(球场70-80%): 只是尝试插入.如果失败,行已经创建.不需要担心并发,因为TRY / CATCH处理重复. BEGIN TRY
INSERT Table VALUES (@Value)
SELECT @id = SCOPEIDENTITY()
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE -- only error was a dupe insert so must already have a row to select
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
主要选择: 类似的,但是尝试先获取数据.没有数据=需要INSERT.再次,如果两个并发调用尝试插入,因为它们都发现该行缺少TRY / CATCH句柄. BEGIN TRY
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
IF @@ROWCOUNT = 0
BEGIN
INSERT Table VALUES (@Value)
SELECT @id = SCOPEIDENTITY()
END
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
第二个似乎重复,但它是高度并发的.锁将实现相同但以并发为代价… 编辑: 为什么不使用MERGE? 如果使用OUTPUT子句,它将只返回更新的内容.所以你需要一个虚拟UPDATE来为OUTPUT子句生成INSERTED表.如果您必须使用许多调用(由OP隐含)进行虚拟更新,那么这是很多日志写入才能够使用MERGE. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- 在SQL Server中使用FOR XML PATH查询分层数据的XML输出
- sql-server – 锁定SQL Server数据库
- 如何在Azure中设置部署,以便根据环境使用不同的数据库?
- LINQ to SQL EntitySet中的漏洞抽象
- 将数据从SQL Server导出到Excel(SSIS)时如何避免“存储为文
- sql-server – 为BACKUP命令设置BUFFERCOUNT,BLOCKSIZE和MA
- sql-server – SQL Server – 基于GUID的PK是支持基于租户的
- 指针数据不存储在本地数据库中,解析ios
- Redis中主键失效的原理及实现机制剖析
- SQL Server触发器和事务用法示例
