データベースの競合状態をどのようにテストしますか?


30

データベースコードを記述して、競合状態にならないようにし、正しい行またはテーブルをロックしたことを確認します。しかし、私はしばしば疑問に思う:私のコードは正しいですか?既存の競合状態を明示的に強制することは可能ですか?実稼働環境でそれらが発生した場合、私のアプリケーションが正しいことを行うことを確認したいと思います。

私は通常、どの同時クエリが問題を引き起こす可能性があるかを正確に知っていますが、正しい動作が発生するかどうかを確認するためにそれらを同時に実行する方法を知りません(たとえば、正しいタイプのロックを使用しました)投げられるなど

注:私はPostgreSQLとPerlを使用しているため、これに一般的に答えることができない場合は、おそらくそのようにタグ付けし直す必要があります。

更新:ソリューションがプログラマティックである場合、それを好むでしょう。そうすれば、自動化されたテストを作成して、回帰がないことを確認できます。


「競合状態」とは、「デッドロック」を意味しますか?
ガイウス

2
@Gaius ...いいえ、私はそれがいくつかの競合状態の可能性のある結果の1つであると信じています
-xenoterracide

データベースの@Gaius競合状態は、作成前にテーブルを削除したり、挿入される前に行を更新したりすることを行います。一般的に、データベース自体の外部のアプリケーションロジックによって処理されると思います。
マークD

挿入される前に行を更新しますか?それはデータベースの問題を引き起こしません。競合状態は行をフェッチして更新するようなものではありませんが、行がフェッチされた後、更新が処理される前に別のユーザーに更新させることです。
-xenoterracide

1
@MarkD-いいえ。アトミックな作業単位をデータベースに誤ってカプセル化することから生じる多くのタイプの競合状態があります。 以下に例を示します。「競合状態または競合危険性は、電子システムまたはプロセスの欠陥であり、プロセスの出力または結果は、他のイベントのシーケンスまたはタイミングに予期せずに決定的に依存します。」(ソース
ニックチャマス

回答:


11

私はいつもT-SQLモジュールでそれをしています。

基本的に、必要なことは、2つ以上の接続からモジュールを数分間ループで実行することだけです。通常、適切なCPUを搭載したSQL Serverボックスがある場合、潜在的な問題はすべて数分で公開されます。

ここここにいくつかの例を書きました。


4

通常、RDBMSのコマンドラインツールを使用し、CLIの2つ(またはそれ以上)のインスタンスを起動します。その後、アプリケーションレイヤーが送信するSQLステートメントを1つずつ再生し、レース(アクションRPGのように見える)として再生できます。CLIが少し「ハング」し、他のCLIからロックが解放されるのを待つので、動作中のロックシステムを実験/感じる必要があります。

これが泥のようにはっきり聞こえる場合は、そう言うことをsoしないでください;-)


ステップごとに例を挙げていただけますか?また、同じことを行うためにプログラムによるテストを作成できますか?
xenoterracide

1

競合状態には複数の実行スレッドが必要です。したがって、これを単体テストするには、1つ以上のスレッドを開始できる必要があります。Oracleでは、DBMS_Schedulerを使用してプロセスを実行し、2番目のユーザーをシミュレートします。PostgreSQL / Perlがプログラムで2番目のプロセスを開始する方法を持っている場合、次のようなことができるはずです。

プロセス1プロセス2

プロセス2を開始します。>>                            
2が作業できるように遅延します。 
。行をロックするか、データを変更します。
。1が作業できるように遅延します。
行のロックまたはデータの変更を試みます。。
適切な処理が行われていることを確認してください。。
終了。。
                                                終了。

競合状態の処理方法、さらに重要なこととしてそれらを単体テストする方法について考えるのは良いことです。


ユニットテストは毎回まったく同じ方法で実行する必要があるため、このようなテストをユニットテストとは言いません。競合状態は、関連するプロセスを断続的に失敗させ、毎回まったく同じ方法ではありません。
AK

@AlexKuznetsov 予期しない競合状態が断続的に表示されることは間違いありませんが、OPはコードが処理していると思われる予期される状態を参照しています。これらの特定の条件を正確に再現し、ユニットテストで処理を検証できます。
リーリフェル

-2

行をロックしている限り、通常はロックが設定されていないときに発生するため、競合状態になることはありません。

しかし、1つの質問があなたの質問を長すぎる間ブロックすると、デッドロックになる可能性があります。

データベースが大きくなるとクエリの時間が変わる可能性があるため、これをテストするのは困難です。

テストデータの100,000行で正常に機能するクエリは、10000行でチャートから外れます。

このタイプの問題は、事前に見つけるのが非常に難しい場合がありますが、多くのDBには、遅いクエリを識別する方法があります。

定期的に使用することで、十分な警告でトラブルに向かうクエリをトラップできるはずです。

あなたが自分でロックを行うと、その別の話ですが、そこでは仕方がありません。


@darioo lol多分wnは何かの頭字語だと思った... idk彼が「自分でロックする」とはどういう意味か彼がORMを使わないということなら、ORMが出力するコードをチェックして、右ロック。これが、潜在的な競合状態のシナリオをテストできるようにしたい理由の1つです。
xenoterracide

はい、私は自分のもので、通常はデータベースドライバのハンドルがロック、行、テーブルまたは可能性フィールドが、私はただのロック処理しないあなたには、いくつかのDBを使用している可能性のために開放しています;)

私は私のDBを自動的にロックする行を知ることができませんことを...のようなものは、複数のステートメントのトランザクションがある場合..私はかなり確信しているselect for update彼らがした場合には存在しなかったでしょうが...
xenoterracide
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.