1

私が以下を持っている場合:

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

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

複数のユーザーが上記のコードを実行している場合、各挿入には一意の増加数がありますか?

言い換えると、beginトランザクションは他のトランザクションをキューに入れ、各挿入が正しいシーケンス番号を持つように読み取りさえしますか?または、Insert into..Selectステートメントを使用して目的を達成する必要がありますか?

ありがとう。

4

5 に答える 5

2

いいえ、デフォルトのSQL Server分離レベル(READ COMMITTED)を使用したトランザクションでは不十分です。それを1つのステートメントに入れてINSERT...SELECTも、修正されません。これを修正するには、基本的に2つのオプションがあります。

オプション1:分離レベルをSERIALIZABLEに設定します:SET TRANSACTION ISOLATION LEVEL SERIALIZABLE。これにより、2人の異なるユーザーからのトランザクションが、順番に発生したのように確実に発生します。ただし、このようなトランザクションの多くが並行して発生する場合、これによりデッドロックが発生する可能性があります。

オプション2:トランザクションの開始時にテーブルを排他的にロックします(SELECT * FROM table WITH (TABLOCKX, HOLDLOCK) WHERE 1=0)。table頻繁に使用すると、パフォーマンスに影響を与える可能性があることに注意してください。

両方のアプローチは、次のSO質問に対する私の回答で詳細に分析されています。

于 2012-07-15T10:29:48.013 に答える
1

レコードを一意に挿入する場合は、最初にシーケンスで作成し、次にレコードをシーケンスに挿入する必要があります。

create sequnce seq_num ;

seq_numここで、rcordsを挿入するために使用します。

insert into <table name>(col1) values(seq_num.nextval);
于 2012-07-15T09:53:26.030 に答える
1

私はかつてSQLDBを大量のデータエクスポートのロガーとして使用し、シーケンシャルな「ID」を取得するために、次の番号の発行を処理する「挿入時」トリガーを作成しました。私にとってはうまくいきましたが、それはシングルユーザー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)

行く

于 2012-07-15T08:50:28.423 に答える
1

いいえ、トランザクションはコマンドをキューに入れません。ロックとは異なります。

通常は ID 列を使用しますが、場合によっては、SequenceNumber 列に一意の制約を指定して上記のコードを使用し、コミット トランザクションが例外をスローした場合に再試行できるように、ギャップなしで SequenceNumber を生成する必要があります。

于 2012-07-15T08:17:59.700 に答える
1

トランザクションの分離レベルを、適切な分離レベルを提供するレベルに設定する必要があります。あなたのコードでは、2 つのプロセスが最初の行を実行し、次に 2 行目を実行する可能性があります。どちらも同じ値を挿入します。

分離レベルをシリアライズ可能に設定し、select ステートメントを実行しますWITH (UPDLOCK)。これにより、システムの同時実行性が低下しますが、安全です。

他の戦略も可能ですが、実装 (およびテスト!) に時間がかかります。

于 2012-07-15T10:23:13.447 に答える