繁体   English   中英

插入序列号表

[英]Inserting into a table with sequence number

如果我有以下内容:

Begin transaction
 numberOfRecords = select count from table where foreignKey = "some value" 

 Insert into table (set SequenceNumber = numberOfRecords + 1)
End Transaction

并且有多个用户正在执行上述代码,那么每个插入内容的编号都会增加吗?

换句话说,开始事务是否使其他事务排入队列甚至读取,以便每个插入都具有正确的序列号? 还是我需要Insert into..Select语句来实现我想要的?

谢谢。

否,具有默认SQL Server隔离级别(READ COMMITTED)的事务不足。 将其放入一个INSERT...SELECT语句也不会修复它。 基本上,您有两种方法可以解决此问题:

选项1 :将隔离级别设置为SERIALIZABLE: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 这将确保来自两个不同用户的交易就像顺序发生一样 但是,如果许多此类事务并行发生,则可能会产生死锁。

选项2 :在事务开始时以独占方式锁定表( SELECT * FROM table WITH (TABLOCKX, HOLDLOCK) WHERE 1=0 )。 请注意,如果经常使用table ,这可能会影响性能。

我对以下SO问题的回答中已详细分析了这两种方法:

不,事务不使命令排队,它不像锁。

通常,您想使用一个身份列,但是在某些情况下,当您想要无间隙地生成SequenceNumber时,您需要使用上面的代码对SequenceNumber列具有唯一约束,并准备在提交事务引发异常时重试。

我曾经使用SQL DB作为海量数据导出的记录器,以获得顺序的“身份”,我创建了一个“插入时”触发器,用于处理下一个数字。 对我来说效果很好,但是它只有一个用户数据库,因此不确定多个用户以及我的工作是否存在任何问题。

现在,我已经重新阅读了问题,这可能不是您想要的,但是我认为您也可以触发选择吗?

USE [ExportLog]
GO

/****** Object:  Trigger [dbo].[Migration_Update_Event_Date]    Script Date: 02/10/2011                17:06:11 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TRIGGER [dbo].[Migration_Update_LogState]
ON [dbo].[MigrationLog] FOR INSERT NOT FOR REPLICATION
AS
UPDATE [MIGRATION-DATA].dbo.MIGRATIONSTATE
SET LASTPROCESSID = ID
WHERE MACHINENAME IN (SELECT MACHINENAME FROM INSERTED)

如果要以唯一的方式插入记录,则首先要在序列上创建,然后记录应插入thorugh序列。

create sequnce seq_num ;

现在使用seq_num插入rcords。

insert into <table name>(col1) values(seq_num.nextval);

您需要将事务隔离级别设置为提供正确隔离级别的级别。 在您的代码中,两个进程可以执行第一行,然后执行第二行。 两者将插入相同的值。

将隔离级别设置为可序列化,然后执行select语句WITH (UPDLOCK) 这样可以减少系统中的并发性,但是很安全。

其他策略也是可能的,但是它们实施(和测试!)的时间更长。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM