データベースに同時にアクセスするにはどうすればよいですか?答えは ロック
です。
推奨: 「mysql ビデオ チュートリアル 」
次に、データベースのロック メカニズムについて説明します。データベースにはどのようなロックがあるでしょうか?
まず第一に、ロックは同時実行制御テクノロジであり、複数のユーザーが同時に同じデータにアクセスするときにデータを保護するために使用されます。
2 つの基本的なロック タイプがあります:
共有 (S) ロック: 複数のトランザクションが共有ページをブロックできます。どのトランザクションもページを変更できません。通常、ページがが読み取られると、S ロックは直ちに解除されます。 select文を実行する際、操作対象(テーブルや一部のレコード)に共有ロックを追加する必要がありますが、ロックを追加する前に排他ロックがあるかどうかを確認する必要があります。排他ロックがない場合は、共有ロックを追加できます。 (N 個の共有ロックをオブジェクトに追加できます)、そうでない場合は機能しません。共有ロックは通常、select ステートメントの実行後に解放されますが、もちろん、主にデータベースによって設定されたトランザクション分離レベルに応じて、トランザクションの終了時 (正常終了および異常終了を含む) に解放される場合もあります。
排他 (X) ロック: このページをブロックできるトランザクションは 1 つだけです。他のトランザクションは、X ロックが解放されるまで待ってからページにアクセスする必要があります。X ロックはトランザクションが終了するまで解放できません。 。 insert、update、delete ステートメントを実行するときは、操作対象のオブジェクトに排他ロックを追加する必要があります。排他ロックを追加する前に、オブジェクトに他のロックがないことを確認する必要があります。排他ロックを追加すると、オブジェクトに他のロックを追加することはできません。任意のロック。排他ロックは通常、トランザクションの終了時に解放されます (もちろん例外もあります。つまり、データベース トランザクション分離レベルが Read Uncommitted (コミットされていないデータの読み取り) に設定されている場合、この場合、排他ロックはトランザクションの終了後に解放されます)。更新操作が完了しました)、トランザクションの終了時ではなく、解放されました)。
ロックの仕組み
ロックを使用しているため、デッドロックが発生する可能性があります。
デッドロックに必要な 4 つの条件:
相互に排他的な条件: リソースは一度に 1 つのプロセスのみ使用できます。
要求と保持の条件: リソースの要求によりプロセスがブロックされた場合、取得したリソースは保持されます。
非剥奪条件: プロセスによって取得されたリソースは、使い果たされる前に強制的に剥奪することはできません。
ループ待機条件: 複数のプロセスがリソース関係を待機する先頭から末尾までのループを形成します。
システムでデッドロックが発生する限り、これらの条件が満たされる必要があり、上記の条件のいずれかが満たされない限り、デッドロックは発生しません。
デッドロックの防止
デッドロックの発生を防ぐには、デッドロックの発生に必要な 4 つの条件のうち 1 つを解消するだけで済みます。
1) 相互排他条件を破棄します
すべてのシステム リソースの共有が許可されている場合、システムはデッドロック状態にはなりません。ただし、一部のリソースは同時にアクセスできず、プリンターなどの重要なリソースは相互に排他的にのみ使用できます。したがって、デッドロックを防ぐために相互排他条件を破壊することは現実的ではなく、場合によっては、この相互排他性を保護する必要があります。
2) 譲渡不可能な条件の破棄
譲渡不可能なリソースを保持しているプロセスが新しいリソースを要求したが満たされない場合、保持しているすべてのリソースを解放し、必要に応じて再適用する必要があります。将来的に必要となります。これは、プロセスによってすでに占有されているリソースが一時的に解放または剥奪されるか、それによって譲渡不可能な条件に違反することを意味します。
この戦略は実装が比較的複雑です。取得したリソースを解放すると、前の段階の作業が失敗する可能性があります。リソースの申請と解放を繰り返すと、システムのオーバーヘッドが増加し、システムのスループットが低下します。この方法は、CPU レジスタやメモリリソースなど、状態の保存や復元が容易なリソースによく使用されますが、プリンタなどのリソースには通常使用できません。
3) リクエストと保持の条件を破棄します
事前静的割り当て方法を使用します。つまり、プロセスは、実行前に必要なすべてのリソースに一度適用されます。リソースが満たされる前に。 、それは動作しません。一度動作を開始すると、これらのリソースは常にそのリソースによって所有され、他のリソース要求は行われないため、システムがデッドロックすることはありません。
この方法は実装が簡単ですが、欠点も明らかです。システム リソースが大幅に浪費されます。これらのリソースの一部は、実行の開始時または実行の終了近くでのみ使用される場合や、場合によっては実行の終了時のみに使用される場合もあります。全く使われていない。また、あるリソースが他のプロセスに長時間占有されると、そのリソースを待っていたプロセスの起動が遅れてしまう「スタベーション」現象も発生します。
4) ループ待ち状態の解消
ループ待ち状態を解消するには、逐次リソース割り当て方式を使用できます。まず、システム内のリソースに番号を付け、各プロセスが番号の昇順でリソースを要求する必要があることを規定し、同様のリソースはすべて一度に要求できるようにします。言い換えれば、プロセスがリソース Ri の割り当てを適用する限り、そのプロセスは将来のリソース アプリケーションで Ri より大きい番号のリソースのみを適用できます。
この方法の問題は、番号付けが比較的安定している必要があり、新しいタイプの機器の追加が制限されることです。リソースに番号を付ける際には、ほとんどのジョブがこれらのリソースを実際に使用する順序が考慮されますが、多くの場合、次のようなことが起こります。ジョブがリソースを使用する順序がシステムで指定された順序と異なる場合、リソースが無駄に使用されるだけでなく、指定された順序でリソースを申請するこの方法は、ユーザーのプログラミングに支障をきたすことは避けられません。
デッドロックの解消
1) デッドロック プロセスからリソースを剥奪します;
2) 一部またはすべてのプロセスを終了します;
MySQL ロックの粒度 (つまり、ロック レベル)
MySQL ストレージ エンジンは、行レベルのロック、ページレベルのロック、テーブルレベルのロックという 3 つのタイプ (レベル) のロック メカニズムを使用します。
1. テーブルレベルのロック: テーブル全体を直接ロックします。ロック期間中、他のプロセスはテーブルに書き込むことができません。書き込みロックがある場合、他のプロセスは読み取りを許可されません。特徴: 低いオーバーヘッド、高速なロック、デッドロックなし、最大のロック粒度、最高のロック競合確率、最低の同時実行性。
MyISAM ストレージ エンジンはテーブル レベルのロックを使用します。
テーブル共有読み取りロックとテーブル排他的書き込みロックの 2 つのモードがあります。読み取りロックを追加するコマンド: lock table table name read; ロックを削除するコマンド: テーブルのロックを解除します。
同時挿入のサポート: クエリと挿入操作の同時実行をサポートします (テーブルの最後に同時挿入)。
ロック スケジュール メカニズム: 書き込みロックの優先順位。プロセスが MyISAM テーブルの読み取りロックをリクエストし、同時に別のプロセスも同じテーブルの書き込みロックをリクエストしました。MySQL はこれをどのように処理しますか?答えは、書き込みプロセスが最初にロックを取得するからです。
2. 行レベルのロック: 他のプロセスが同じテーブル内の他のレコードを操作できるように、指定されたレコードのみをロックします。特徴: 高いオーバーヘッド、遅いロック、デッドロックが発生する可能性がある、ロックの粒度が最も小さく、ロック競合の可能性が最も低く、同時実行性が最も高い。
InnoDB ストレージ エンジンは行レベルのロックとテーブルレベルのロックの両方をサポートしますが、デフォルトでは行レベルのロックが使用されます。
3. ページレベルのロック: 隣接するレコードのグループを一度にロックします。オーバーヘッドとロック時間はテーブル ロックと行ロックの間であり、デッドロックが発生します。ロックの粒度はテーブル ロックと行ロックの間で、同時実行性は平均的です。
複数のユーザーによる同時アクセスを処理するために最も一般的に使用される方法はロックです。ユーザーがデータベース内のオブジェクトをロックすると、他のユーザーはそのオブジェクトにアクセスできなくなります。同時アクセスに対するロックの影響は、ロックの粒度に反映されます。たとえば、(テーブル ロック) テーブルに設定されたロックはテーブル全体への同時アクセスを制限します。(ページ ロック) データ ページに設定されたロックはデータ ページ全体へのアクセスを制限します。(行ロック) 行に設定されたロックロックは、行への同時アクセスのみを制限します。
楽観的ロックと悲観的ロックの概念、実装方法、および使用シナリオ
ロック機構には、悲観的ロックと楽観的ロックの 2 つがあります。
悲観ロックは、その名前が示すように、世界を悲観しており、変化するデータに他人がアクセスする可能性が非常に高いと考え、データが変化し始めてから変化するまでデータをロックします。変更が完了してから解放されます。
典型的なデータベース依存の悲観的ロック呼び出し:
Select * from account where name="Erica" for update
この SQL ステートメントは、アカウント内のすべてのエントリをロックしますtable 検索条件 (name="Erica") に一致するレコード。このトランザクションがコミットされる前は (トランザクション中のロックはトランザクションがコミットされると解放されます)、外部はこれらのレコードを変更できません。このステートメントは、特定の行をロックするために使用されます (where 句がある場合は、where 条件を満たす行です)。これらの行がロックされている場合、他のセッションはこれらの行を選択できますが、コミット ステートメントまたはロールバック ステートメントによってステートメントのトランザクションが終了するまで、これらの行を変更または削除することはできません。 select...for update は MySQL トランザクション タイプ、つまり begin と commit に配置する必要があることに注意してください。そうしないと機能しません。
悲観的な見方をすると、ロックに時間がかかり、特にトランザクションが長くなり、ロックの発行が適切に行われない可能性があり、システム全体のパフォーマンスに影響を与える可能性があります。
悲観的ロックの実装方法:
悲観的ロックもデータベース ロックのメカニズムに基づいて実装されます。このようなロック メカニズムの多くは、行ロック、テーブル ロック、読み取りロック、書き込みロックなど、従来のリレーショナル データベースで使用されており、操作前にすべてロックされます。
楽観的ロックは世界について楽観的であり、変更中のデータに他の人がアクセスする可能性は非常に低いと考えます。したがって、変更が完了し、変更を送信する準備ができるまで、データはロックされません。オブジェクトの読み取りおよび変更を行うときにオブジェクトをロックせず、変更が完了した後にオブジェクトを解放する場合。オプティミスティック ロックではダーティ リードの問題を解決できません。
楽観的ロックのロック時間は悲観的ロックよりも短く、大規模な同時実行下でのシステム全体のパフォーマンスが大幅に向上します。
楽観的ロックの実装方法:
1. 多くはデータのバージョン(バージョン)記録の仕組みに基づいており、データの各行にバージョン識別子を付加する必要があります。つまり、データの各行に 1 つのフィールドが追加されます).version)、データが更新されるたびに、対応するバージョン番号 1 を更新する必要があります。
動作原理: データを読み取るときは、このバージョンを一緒に読み取り、後で更新するときは、このバージョン番号に 1 を加えます。この際、入稿データのバージョン情報とデータベーステーブルの該当レコードの現在のバージョン情報を比較し、入稿データのバージョン番号がデータベーステーブルの現在のバージョン番号より大きい場合は、それ以外の場合は、期限切れデータとみなされ、再度読み取る必要があります。オブジェクトを取得して変更を加えます。
2. タイムスタンプを使用して実装します
また、オプティミスティック ロック制御を必要とするテーブルにフィールドを追加します。名前は重要ではありません。フィールド タイプはタイムスタンプを使用します。これは上記のバージョンと同様です。 . 更新が送信されるときも、現在のデータベース内のデータのタイムスタンプがチェックされ、更新前に取得されたタイムスタンプと比較されます。一致していれば問題ありませんが、そうでない場合はバージョンの競合です。
悲観的ロックと楽観的ロックの適用可能なシナリオ:
同時実行の量が大きくない場合は、悲観的ロックを使用して同時実行の問題を解決できます。システム内の同時実行の量が非常に多いため、悲観的な考え方は非常に大きなパフォーマンスの問題を引き起こすため、楽観的なロック方法を選択する必要があります。現在、ほとんどのアプリケーションは楽観的にロックされるはずです。
以上がMySQL のロックに関連する問題の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。