タグ付けされた質問 「concurrency」

複数のユーザーまたはプロセスがデータベースシステムの共有情報に同時にアクセスまたは変更するときに発生する問題についての質問。

1
Postgres UPDATE…LIMIT 1
サーバーステータス(「アクティブ」、「スタンバイ」など)などのサーバーのクラスターに関する詳細を含むPostgresデータベースがあります。アクティブなサーバーはいつでもスタンバイにフェールオーバーする必要があり、特にどのスタンバイが使用されているかは気にしません。 データベースクエリでスタンバイのステータス(JUST ONE)を変更し、使用するサーバーIPを返すようにします。選択は任意です。サーバーのステータスはクエリによって変化するため、どのスタンバイが選択されているかは関係ありません。 クエリを1つの更新のみに制限することはできますか? ここに私がこれまで持っているものがあります: UPDATE server_info SET status = 'active' WHERE status = 'standby' [[LIMIT 1???]] RETURNING server_ip; Postgresはこれを好まない。別に何ができますか?

5
PostgreSQLでの同時DELETE / INSERTのロックの問題
これは非常に簡単ですが、PG(v9.0)の機能に困惑しています。簡単な表から始めます。 CREATE TABLE test (id INT PRIMARY KEY); 数行: INSERT INTO TEST VALUES (1); INSERT INTO TEST VALUES (2); お気に入りのJDBCクエリツール(ExecuteQuery)を使用して、2つのセッションウィンドウをこのテーブルが存在するdbに接続します。両方ともトランザクション対応です(つまり、auto-commit = false)。それらをS1およびS2と呼びましょう。 それぞれに同じコードのビット: 1:DELETE FROM test WHERE id=1; 2:INSERT INTO test VALUES (1); 3:COMMIT; 次に、これをスローモーションで実行し、ウィンドウで1つずつ実行します。 S1-1 runs (1 row deleted) S2-1 runs (but is blocked since S1 has a write …

4
データベースの競合状態をどのようにテストしますか?
データベースコードを記述して、競合状態にならないようにし、正しい行またはテーブルをロックしたことを確認します。しかし、私はしばしば疑問に思う:私のコードは正しいですか?既存の競合状態を明示的に強制することは可能ですか?実稼働環境でそれらが発生した場合、私のアプリケーションが正しいことを行うことを確認したいと思います。 私は通常、どの同時クエリが問題を引き起こす可能性があるかを正確に知っていますが、正しい動作が発生するかどうかを確認するためにそれらを同時に実行する方法を知りません(たとえば、正しいタイプのロックを使用しました)投げられるなど 注:私はPostgreSQLとPerlを使用しているため、これに一般的に答えることができない場合は、おそらくそのようにタグ付けし直す必要があります。 更新:ソリューションがプログラマティックである場合、それを好むでしょう。そうすれば、自動化されたテストを作成して、回帰がないことを確認できます。

3
SELECT-UPDATEパターンを使用する場合の同時実行性の管理
次のコードがあるとしましょう(ひどいことは無視してください): BEGIN TRAN; DECLARE @id int SELECT @id = id + 1 FROM TableA; UPDATE TableA SET id = @id; --TableA must have only one row, apparently! COMMIT TRAN; -- @id is returned to the client or used somewhere else 私の目には、これは並行性を適切に管理していません。トランザクションがあるからといって、更新ステートメントに到達する前に他の誰かがあなたと同じ値を読み取らないということにはなりません。 今、コードをそのままにしておきます(これは単一のステートメントとして処理するか、自動インクリメント/ ID列を使用することをお勧めします)並行性を適切に処理し、2つのクライアントが同じになる競合状態を防ぐ確実な方法id値? WITH (UPDLOCK, HOLDLOCK)SELECTにa を追加するとうまくいくと確信しています。SERIALIZABLEトランザクション分離レベルは、(それは誰にもTRANが終わるまで、あなたが何をしたか読むことを拒否したことから、同様の作業に思えるでしょうUPDATE:これは偽であることがわかりマーティンの答え)。本当?どちらも同等に機能しますか?一方が他方よりも優先されますか? IDの更新よりも正当なもの、つまり更新が必要な読み取りに基づいた計算を行うことを想像してください。多数のテーブルが関係している可能性がありますが、そのうちのいくつかは書き込みを行い、他のテーブルは書き込みを行いません。ここでのベストプラクティスは何ですか? この質問を書いた後、必要なテーブルのみをロックしているので、ロックヒントの方が優れていると思いますが、誰かの入力に感謝します。 PSそして、いいえ、私は最良の答えを知りません、そして、本当に、より良い理解を得たいです!:)

6
SQL Server IDの値を順番に読み取ることに依存できますか?
TL; DR:次の質問に要約します:行を挿入するとき、新しい値の生成とクラスター化インデックス内の対応する行キーのロックの間に機会がありますか?外部オブザーバーはより新しいものを見ることができます並行トランザクションによって挿入された値?(SQL Serverで。)Identity Identity 詳細バージョン Identityという名前の列を持つSQL ServerテーブルがありますCheckpointSequence。これは、テーブルのクラスター化インデックスのキーです(これには、追加の非クラスター化インデックスもいくつかあります)。行は、いくつかの並行プロセスとスレッドによって(分離レベルで、なしで)テーブルに挿入されます。同時に、クラスター化インデックスから定期的に行を読み取るプロセスがあり、その列で並べ替えられます(分離レベルでも、オプションはオフになっています)。READ COMMITTEDIDENTITY_INSERTCheckpointSequenceREAD COMMITTEDREAD COMMITTED SNAPSHOT 私は現在、読み取りプロセスがチェックポイントを「スキップ」できないという事実に依存しています。私の質問は、このプロパティに依存できますか?そうでない場合、それを実現するために何ができますか? 例:ID値が1、2、3、4、および5 の行を挿入する場合、値4の行を表示する前に、値5の行を参照してはなりません。テストは、ORDER BY CheckpointSequence句(そしてWHERE CheckpointSequence > -1確実句)、ブロック行4、行5が既にコミットされていても、読まれるべきであるが、まだコミットされていない時はいつでも。 少なくとも理論的には、この仮定を破る可能性のある競合状態がここにあると思います。残念ながら、上のドキュメントでIdentityはIdentity、複数の同時トランザクションのコンテキストでどのように機能するかについてはあまり言及されていません。「特定のトランザクションの新しい値はそれぞれ、テーブル上の他の同時トランザクションとは異なります。」(MSDN) 私の推論は、それはこのように何らかの形で動作する必要があります: トランザクションが(明示的または暗黙的に)開始されます。 ID値(X)が生成されます。 対応する行ロックは、ID値に基づいてクラスター化インデックスで取得されます(ロックエスカレーションが開始されない限り、この場合、テーブル全体がロックされます)。 行が挿入されます。 トランザクションがコミットされる(おそらくかなり長い時間後に)ので、ロックは再び削除されます。 ステップ2と3の間に、非常に小さなウィンドウがあると思います 同時セッションは次のID値(X + 1)を生成し、残りのすべてのステップを実行できます。 したがって、その時点で正確に来ている読者が値X + 1を読み取ることができ、Xの値は失われます。 もちろん、これの可能性は非常に低いようです。しかし、まだ-それは起こる可能性があります。それともできますか? (コンテキストに興味がある場合:これは、NEventStoreのSQL Persistence Engineの実装です。NEventStoreは、すべてのイベントが新しい昇順チェックポイントシーケンス番号を取得する追加専用のイベントストアを実装します。クライアントは、チェックポイント順にイベントストアからイベントを読み取りますすべての種類の計算を実行するため。チェックポイントXのイベントが処理されると、クライアントは「新しい」イベント、つまりチェックポイントX + 1以上のイベントのみを考慮します。したがって、イベントをスキップしないことが重要です。現在、Identityベースのチェックポイント実装がこの要件を満たしているかどうかを判断しようとしています。これらは、使用されている正確なSQLステートメントです。Schema、Writerのquery、読者の質問。) 私が正しいと上記の状況が発生する可能性がある場合、それらに対処する2つのオプションのみが表示されますが、どちらも不十分です。 Xを確認する前にチェックポイントシーケンス値X + 1を確認した場合は、X + 1を終了し、後で再試行してください。ただし、Identityもちろんギャップが発生する可能性があるため(たとえば、トランザクションがロールバックされるとき)、Xが来ることはありません。 したがって、同じアプローチですが、nミリ秒後にギャップを受け入れます。ただし、nのどの値を想定する必要がありますか? より良いアイデアはありますか?


1
部分的に更新された行を読みますか?
SSMSの2つの個別のセッションで実行される2つのクエリがあるとします。 最初のセッション: UPDATE Person SET Name='Jonny', Surname='Cage' WHERE Id=42 2番目のセッション: SELECT Name, Surname FROM Person WITH(NOLOCK) WHERE Id > 30 SELECTステートメントが半分更新された行、たとえばName = 'Jonny'andを含む行を読み取ることは可能Surname = 'Goody'ですか? クエリは、別々のセッションでほぼ同時に実行されます。

3
存在しない場合は同時に挿入
ストアドプロシージャへの挿入で並行性の問題が発生しています。手順の関連部分は次のとおりです。 select @_id = Id from table1 where othervalue = @_othervalue IF( @_id IS NULL) BEGIN insert into table1 (othervalue) values (@_othervalue) select @_id = Id from table1 where othervalue = @_othervalue END これらのストアドプロシージャを3つまたは4つ同時に実行すると、複数の挿入が発生することがあります。 私はこれを次のように修正することを計画しています: insert into table1 (othervalue) select TOP(1) @_othervalue as othervalue from table1 WITH(UPDLOCK) where NOT EXISTS …

1
高度な並行ストレージシステム
たとえば、それぞれ300億行(合計サイズ4TB)の3つの巨大なテーブル(構造化データ)があり、多数の同時ユーザー(リモートLANマシンの並列osスレッド)が一部を読み取る必要があることを想像してくださいSELELCT WHERE GROUPBYクエリと非常に同時、たとえば10,000同時読み取りによるデータと、ユーザーがこれらのテーブルにデータを挿入する必要があります(更新なし)2000同時書き込み(データセンターLANネットワーク全体) 。ユーザーは、このストレージから可能な限り高速で読み取りと挿入を行い、各読み取りと書き込みが行われる場所はms〜1秒の範囲です。 そのような要件を満たすために、どのテクノロジーをお勧めしますか?これを実行できるデータストレージまたはキーバリューストアはありますか?クラウドはオプションではありません。 いくつかの明確化: ユーザーはデータをすぐに見る必要はなく、最終的な一貫性は許容されます。データはストレージが提供できるドライバーを介してアクセスされ、ユーザーは再びデータセンターのリモートマシンで実行される単なるスレッドになります。クエリは、主にSELECT WHERE GROUPBYに似ています。 データは表形式で、各行は約60バイトです。 DynamoDBまたは同様のソリューションを使用できないクラウドオプションはありません。データセンターで内部的にホストできる必要があります。 テーブルのすべてのデータを常に読み取ることができ、使用パターンは予測できません。結合または超長いクエリはありません。DRは必要ありませんが、合理的なHAは必要ですが、空想である必要はありません。すべての読者は、where句に基づいて行のバッチを取得しており、行は実際には関連していません。各行の長さを固定することもできますが、ストレージレイヤーが心配することを期待しています。 また、私の最大の懸念は、同時読み取りで発生するすべての同時書き込みです。 これに対するあなたの洞察は非常に高く評価されています。 さらに、これらのテーブルのうち3つにそれぞれ300億行の異なるオブジェクトタイプがあります

1
大量のデータを含む既存のテーブルにインデックスを追加するとどうなりますか?
約1500万件のレコードを含むテーブルがあります。次に、テーブルにインデックスを追加する必要があります。 インデックスを追加すると、テーブルのすべてのエントリが更新されるまでに時間がかかります。 インデックスを追加するとダウンタイムが発生するかどうか、私はかなり混乱しています。 はいの場合、どのようにしてダウンタイムを克服できますか?

1
PostgresでのUPDATE / INSERTの組み合わせのロック
テーブルが2つあります。1つはログテーブルです。もう1つには、基本的に1回しか使用できないクーポンコードが含まれています。 ユーザーはクーポンを利用できる必要があります。これにより、ログテーブルに行が挿入され、クーポンが使用済みとしてマークされます(used列をに更新することによりtrue)。 もちろん、ここには明らかな競合状態/セキュリティ問題があります。 私は過去にもmySQLの世界で同様のことをしたことがあります。その世界では、両方のテーブルをグローバルにロックし、これは一度に1回だけ発生する可能性があるという知識のもとでロジックを安全に実行し、完了したらテーブルのロックを解除します。 Postgresでこれを行うより良い方法はありますか?特に、ロックがグローバルであることを心配していますが、グローバルである必要はありません。他の誰かがその特定のコードを入力しようとしていないことを確認するだけでよいので、行レベルのロックが機能するでしょうか?

2
LATCH_EXリソースMETADATA_SEQUENCE_GENERATORで待機
インベントリレポートを生成するプロセスがあります。クライアント側では、プロセスは構成可能な数のワーカースレッドを分割して、多数(潜在的に数千、通常は数十)のうちの1つのストアに対応するレポートのデータのチャンクを構築します。各ワーカースレッドは、ストアドプロシージャを実行するWebサービスを呼び出します。 各チャンクを処理するためのデータベースプロセスは、一連のデータを#Temporaryテーブルに収集します。各処理チャンクの最後に、データはtempdbの永続テーブルに書き込まれます。最後に、プロセスの最後に、クライアント側の1つのスレッドが永続的なtempdbテーブルにすべてのデータを要求します。 このレポートを実行するユーザーが多いほど、速度は低下します。データベース内のアクティビティを分析しました。ある時点で、プロセスのある時点で35の個別のリクエストがすべてブロックされているのがわかりました。これらのすべてのSPIDはLATCH_EX、リソースで約50ミリ秒待機していましたMETADATA_SEQUENCE_GENERATOR (00000010E13CA1A8)。1つのSPIDにこのリソースがあり、他のすべてのSPIDがブロックしています。ウェブ検索でこの待機リソースについて何も見つかりませんでした。 使用しているtempdbのテーブルにはIDENTITY(1,1)列があります。これらのSPIDはIDENTITY列を待機していますか?ブロッキングを削減または排除するためにどのような方法を使用できますか? サーバーはクラスターの一部です。サーバーは64ビットのWindows 2008 R2 Enterpriseで64ビットのSQL Server 2012 Standard Edition SP1を実行しています。サーバーには64 GBのRAMと48のプロセッサがありますが、データベースは標準エディションであるため、16しか使用できません。 (このすべてのデータを保持するためにtempdbの永続テーブルを使用する設計にわくわくしないことに注意してください。これを変更することは、技術的および政治的な興味深い課題になりますが、私は提案を受け入れます。) 2013年4月23日更新 マイクロソフトでサポートケースをオープンしました。詳細については、この質問を更新していきます。 2013年5月10日更新 SQL Serverのサポートエンジニアは、待機がIDENTITY列によって引き起こされたことに同意しました。IDENTITYを削除すると、待機がなくなりました。SQL 2008 R2では問題を再現できませんでした。SQL 2012でのみ発生しました。

6
READ UNCOMMITTED分離レベルを使用するのに最適な状況
ご存じのとおり、READ UNCOMMITTEDは、ダーティリードやファントムリードなどが発生する可能性がある最低の分離レベルです。この分離レベルを使用するのに最適な時期はいつですか、どのような理由で使用されるのですか? 実は前に答えを読んでみましたが、例が少ないので完全には理解できませんでした。

1
トランザクションにSelectステートメントを置く
これら2つのクエリの違いは何ですか。 START TRANSACTION; SELECT * FROM orders WHERE id=1; UPDATE orders SET username='John' WHERE id=1; COMMIT; そしてトランザクションなし: SELECT * FROM orders WHERE id=1; UPDATE orders SET username='John' WHERE id=1; SELECTトランザクション内での影響は何ですか? 場合はDELETE FROM orders WHERE id=1、右の後に別のセッションから呼び出されたSELECT両方のケースでは、ときそれが処理されるのですか?

3
反復可能読み取りの不整合
http://www.postgresql.org/docs/9.2/static/transaction-iso.html 反復可能読み取りモードは、各トランザクションがデータベースの完全に安定したビューを見ることを厳密に保証します。ただし、このビューは、必ずしも同じレベルの同時トランザクションのいくつかの(一度に1つの)逐次実行と常に整合しているとは限りません。たとえば、このレベルの読み取り専用トランザクションでも、バッチが完了したことを示すように更新された制御レコードが表示されますが、制御レコードの以前のリビジョンを読み取ったため、論理的にバッチの一部である詳細レコードの1つは表示されません。 。この分離レベルで実行されているトランザクションによってビジネスルールを適用しようとすると、競合するトランザクションをブロックする明示的なロックを注意深く使用しないと、正しく機能しない可能性があります。 これは、反復可能読み取りモードでは不可能なファントム読み取りではありませんか? ドキュメントには、反復可能な読み取りトランザクションのクエリは、トランザクションの開始時のスナップショットが表示されるとありますが、クエリが一貫性のないデータを読み取ることができるのはなぜでしょうか。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.