0

C# で 2 つのスレッドを作成し、2 つの別々の関数を並行して呼び出しています。どちらの関数も、XYZ テーブルから最後の ID を読み取り、値 ID+1 を持つ新しいレコードを挿入します。ここで ID 列が主キーです。両方の関数を実行すると、主キー違反エラーが発生します。以下のクエリを持つ両方の関数:

insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name') 

両方の関数が一度に値を読み取り、同じ値で挿入しようとしているようです。どうすればこの問題を解決できますか..?

4

4 に答える 4

2

ID 列を「Identity」列に設定します。次に、クエリを次のように実行できます。

insert into XYZ values('Name') 

列の作成後に ALTER TABLE を使用して列を Identity に変更することはできないと思います。Managament Studio を使用して、この列を ID に設定します。テーブルに多くの行がある場合、実際にデータを新しいテーブルにコピーする (テーブルの再作成を実行する) ため、これは長時間実行されるプロセスになる可能性があります。

ほとんどの場合、そのオプションは Managament Studio で無効になっています。これを有効にするには、[ツール] -> [オプション] -> [デザイナー] を開き、[テーブルの再作成が必要な変更を保存しない] オプションのチェックを外します...テーブルのサイズによっては、おそらくタイムアウトも設定する必要があります。その間、テーブルはロックされます。

于 2013-03-25T04:45:25.150 に答える
2

データベースに ID の選択を処理させます。上記のコードから、本当に必要なのは自動インクリメント整数 ID 列であり、データベースが確実に処理できることは明らかです。したがって、テーブルを適切に設定し、現在の挿入ステートメントの代わりに、次のようにします。

insert into XYZ values('Name') 

データベース テーブルが既に設定されている場合は、次のようなステートメントを発行できると思います。

alter table your_table modify column you_table_id int(size) auto_increment

最後に、これらの解決策のいずれも何らかの理由で適切でない場合 (コメント セクションで示したように、テーブル スキーマを編集できないなど)、コメントで提案された他のユーザーの 1 人として実行し、同期されたメソッドを作成して、次の ID を見つけます。基本的には、int を返す静的メソッドを作成し、その静的メソッドで select id ステートメントを発行し、返された結果を使用して次のレコードをテーブルに挿入します。このメソッドは挿入の成功を保証しないため (外部アプリケーションも同じテーブルに挿入できるため)、例外をキャッチして失敗時に再試行する必要があります)。

于 2013-03-25T04:28:08.097 に答える
0

より高いトランザクション分離レベルまたはより制限的なロックが必要なようです。

私はこれらの機能をあまり頻繁に使用しないので、間違っている場合は誰かが編集を提案してくれることを願っていますが、次のいずれかが必要です。

-- specify the strictest isolation level
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
insert into XYZ values((SELECT max(ID)+1 from XYZ),'Name') 

また

-- make locks exclusive so other transactions cannot access the same rows
insert into XYZ values((SELECT max(ID)+1 from XYZ WITH (XLOCK)),'Name') 
于 2013-03-25T05:23:51.607 に答える
0

このような問題の解決策は、ある種のシーケンスを使用して ID を生成することです。

たとえば、SQL Server では、次のコマンドを使用してシーケンスを作成できます。

CREATE SEQUENCE Test.CountBy1
    START WITH 1
    INCREMENT BY 1 ;
GO

次に、C# で Test から次の値を取得し、それを ID に割り当ててから挿入できます。

于 2013-03-25T04:58:45.860 に答える