なぜロックがあるはず?
データベース設計のロックが時に共有リソースへの複数ユーザーの同時アクセス同時実行の問題を解決するためのものであることを私たちは皆知っています。共有リソースへのアクセスすると、ロックされたユーザーのアクセスルールを意味します。ロックされた範囲は、MySQLのロックは、おおよそのグローバルロック・テーブル・レベル3と行ロックに分割することができます。この記事では、我々は、順番にロックの3種類をご紹介します。この記事を読んだ後に、次の内容を持っている必要があります。
- なぜグローバルロックのバックアップを使用できますか?
- なぜそれをバックアップとしてInnoDBエンジンを使用することをお勧めしますか?
- グローバルな読み取り専用の設定方法
- テーブル・レベル・ロックの二種類
- MDLの原因の問題は、データベースがハングアップします
- ロックの競合を減らすために2フェーズロック・プロトコルを使用する方法
- デッドロックを解決する方法
- ホットテーブルについて、どのように示した損失の検出を避けるために?
グローバルロック
グローバルロックとは何ですか?
ライブラリ全体を行いますグローバルロックは読み取り専用で、他のスレッド文(DML、DDL、更新トランザクションクラス)文がブロックされていたであろう。
グローバルロックシーンを使用します
フルデータベースの論理バックアップを行う場合、ライブラリ全体を選択し、テキストとして保存されます。
なぜグローバルロックを使うのか?
あなたが購入動作更新口座残高や利用者のカリキュラムに設計されているバックアップシステムを、購入したいシナリオを想像してみてください。
ユーザーがコースを購入今論理バックアップ、バックアッププロセスは、その後、その後、コースの購入にコースを追加し、貸借対照表の残高を減算する必要があります。、購入動作を行うコースのバランスを削減し、バックアップ中に増加する確かに正しい順序。しかし、このような問題がある可能性があります。
バランスシート(u_account)をバックアップするための時間でご注文いただいた場合、ユーザーの購入(2つのテーブルを操作する)、再びユーザーのカリキュラム(u_course)アップ?
そして、データのバックアップ、リストアするために行う、ユーザーがレッスンを買うためにお金をかけていないことがわかります。その理由は、ユーザーの残高変わらないことを示す、バランスシートをバックアップすることです。操作後の購入、マイナス貨幣残高、カリキュラムのコースの増加を作ることでした。次にバックアップカリキュラム、カリキュラムのコースプラスワン。バックアップは、バランスシートを完了した後に購入動作を行います。
ユーザーの時間のカリキュラム(u_course)をバックアップするために場合、ユーザーの購入(2つのテーブルを操作する)、再びバランスシート(u_account)アップ?
あなたがカリキュラムをバックアップする場合は同様に、もちろんありません購入するので増加していません。購入後の操作、バランスシートマイナスお金が続き、それがバックアップされます。登場し、ユーザーがお金を使うが、成功して買いませんでした。
言い換えれば、そのライブラリは、バックアップシステムを得るために時間内に論理的なポイントではない、ロックされていない、このビューには、論理的な矛盾です。
問題を解決するためにどのように論理的な矛盾を見ますか?
エンジンに関しては、このようなMyISAMテーブルなどのトランザクションをサポートしていません。使用することによりFlush tables with read lock
グローバルロック(FTWRL)コマンドを開きます。
しかしFTWRL質問の使用があります:
- メインライブラリにバックアップする場合は、更新がバックアップ中に実行することができない、基本的なビジネスが中断しました。
- ライブラリーからのバックアップでは、ライブラリーからメインライブラリーは、マスター・スレーブの遅延につながる、バイナリログの上にバックアップ同期中に行うことができません。
MVCCのエンジン機能(InnoDBの)ビジネスをサポートし、一貫性のあるビュー(反復可能読み取り)を投入すると、バックアップは非常に簡単です。
公式の使用mysqldump
ツール、プラス--single-transaction
のオプションをして、それが一貫性のあるビューを取得するために確保するために、トランザクションを開始する前のデータをエクスポートします。そして、MVCCのサポートのため、とする操作を更新することができます。
全体のライブラリの比較は、読み取り専用の設定方法
なぜ推奨されませんset global readonly=true
FTWRLを使用します:
ライブラリは、メインライブラリーまたはライブラリ装置を決定するために使用されるようないくつかのシステムでは、読み取り専用の値は、他のロジックを実行するために使用されます。そのため、グローバル変数は道に大きな表面に影響を与える変更、それが推奨されていません。
例外処理メカニズムの違いがあります。
クライアントFTWRL異常切断は、その後、MySQLは自動的にグローバルロックを解除するためのコマンドを実行した後、ライブラリ全体は、通常のステータスの更新に戻してもよいです。
ライブラリ全体がクライアントが失敗した場合、データベースが読み取り専用の状態のままになります例外、読み取り専用に設定された後、これは、非書き込み可能な状態で長時間高いリスクをライブラリ全体の原因となります。
テーブル・レベル・ロック
テーブルレベルロックとは何ですか?
二レベルは、MySQL表A表ロックがロックメタデータ(メタデータロック、MDL)であるロックの表ロックは、ロックのための特定のテーブルにスコープされています。
テーブルロック
そしてFTWRL類似し、使用することができlock tables … read/write
、特定のテーブルをロックします。解放時に、使用することができるunlock tables
ロックは、アクティブ解除をリリースまたは切断されたとき。
この方法は、読み書きするために他のスレッドを制限するだけでなく、オブジェクトの独自のオペレーティングスレッドを定義するだけでなく、ロックテーブルことに留意すべきです。
スレッドAが実行された場合lock tables t1 read, t2 write;
の動作を。
テーブルの場合、この時間t1、他のスレッドが読み取り専用ことができ、スレッドAが読み取り専用ことができ、書き込むことはできません。
テーブルT2のために、スレッドAは、他のスレッドがブロックされる読み取りおよび書き込み、読み取り専用しました。
メタデータロック
表異なる手動ロックラッチ、ロックメタデータは自動的に追加されます。
なぜMDL必要がありますか?
MDLは、この場合のときにクエリデータテーブルの構造、テーブル構造とクエリの結果は確かに矛盾しない変更する別のスレッドとして、読み書きの正確さを保証することです。簡単に言えば、** MDLは、DMLとDDLの間で動作しているときに問題を解決することです。
MySQLでは5.5紹介はMDL、DMLの1の時に、DMLロックを読んで追加されます。ときDDL、MDLの書き込みロックを追加します。
読み取りロックの間に相互に排他的ではなく、同じテーブルに複数のスレッドがDMLたことができます。
読み書きロックとの間で、相互に排他的との間に書き込みロックは、チェンジ・テーブル構造の操作の安全性を確保します。
- 同時に開始フィニッシュ実行に別のものを待つために、テーブルにフィールドを追加するには、2つのスレッドがある場合。
- スレッドが読み場合は、別のスレッドを書き込みます。次の表アクセス時間、終了操作は、それが別であってもよいです。
MDLの問題が提起しましたか?
テーブルにフィールドを追加し、ハングアップライブラリにつながっていますか?
MDLは自動的に行われますので、フィールドまたはフィールドが変更またはインデックス、テーブル全体をスキャンするために必要なデータを追加するとき、テーブルに追加されます。大手術台だから、サービスラインに影響を与えないように非常に注意します。しかし、実際には、小さなテーブルを操作するとき、またはすることは間違って行くことがあります。Tは、小さなテーブルを想定しています。図に示されている、4つのオープンセッション。
MySQLの5.7.27
あなたはsync_testと呼ばれるテーブルを持っていると言います。
mysql> desc sync_test;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
オープントランザクション1は、データを挿入します。トランザクション1の場合は、MDLのテーブルsync_testの自動適用は、ロックをお読みください。
オープントランザクション2、挿入データ。トランザクション2の場合は、MDLのテーブルsync_testの自動適用は、ロックをお読みください。
3つの開いている業務は、テーブル構造を変更します。トランザクション3の場合は、申込書がsync_test書き込みロックをMDLなり、原因読み書きロックミューテックスのこの時間はブロックされます。
4つのオープン総務、挿入データ。ミューテックスがブロックされているので、事前にトランザクション3の前に、書き込みロックを適用するためのトランザクション4の場合、それはMDLのsync_testのために適用されますが、ロックをお読みください。
このテーブル上のクエリは非常に頻繁にあり、クライアントが再接続機構を備えている、新しいセッションがタイムアウトした後、要求を更新する場合はその後、このライブラリのスレッドがすぐにいっぱいまでとなります。
テーブルプラスにリソースを確保する方法
上記の例でも見ることができ、MDLは、テーブル構造の変更を行い、トランザクションのコミットまで解放しません、彼らはクエリと更新につながるラインをロックしないように注意する必要があります。トランザクションを開いた後、それが引き起こした、いわゆる長いトランザクションが原因である、短時間で終わりませんでした。長時間トランザクション(INFORMATION_SCHEMA下innodb_trxテーブル)は、テーブルDDLを操作したい場合は、次の時間があり、あなたが最初のクエリ、あなたはその後、DDL操作を行い、トランザクションを殺すことができます。
しかし、時にはキルは、テーブルが頻繁に使用されている場合、新しいトランザクションはすぐにここにも、できないことがあります。理想的には、待機時間中に、ALTERテーブルセット、時間で最高を得るか、あるいはあきらめ、声明をふさがないようにしてくださいする場合。この操作後に繰り返しました。
MariaDBは、これら二つのオープンソースの枝が現在DDL NOWAIT / WAIT nはこの構文をサポートするので、この機能AliSQLを統合しました。
ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ...
行レベルのロック
行レベルのロックとは何ですか?
MySQLの行ロックは、自身がすべてではないすべてのエンジンは、そのようなラインのエンジンをサポートしていないMyISAMテーブルにロックするように、行ロックを行う招待エンジンによって達成されます。行ロックの同時実行制御手段が実装だけで、同時に一つだけの更新が生じたテーブル・ロックを、使用することができますサポートしていません、それは並行処理事業の度合いに影響を与えます。InnoDBは、行ロックがMyISAMの重要な理由によって置き換えられるサポートしています。
行ロックは、データベースのテーブルのレコード内の行をロックされています。このようなトランザクションA、Bが同時にデータの行を更新する、一定の順序更新で実行されますが、同時に更新することはできません。
目的は、並行処理事業の程度を高めるために、テーブル・レベルのような行ロックロック競合を低減することです。
二相ロック・プロトコル
InnoDBのトランザクションでは、行ロックはプラスであるが、必要なときに放出上に使用されるが、二相ロック・プロトコルであるトランザクションの終了後に解放されません。
次のようにテーブル、トランザクション処理のT A、B動作テーブルTが存在すると仮定します。
在事务 A 的两条语句更新后,事务 B 更新操作会被阻塞。直到事务 A 中执行 commit 操作后才能执行。
两阶段锁在事务上的帮助
由于两阶段锁的特点,在事务结束时才会释放锁,所以需要遵循的一个原则是事务中需要锁多个行时,把有可能造成锁冲突,最可能影响并发度的锁尽量向后放。
比如购买课程的例子,顾客 A 购买培训机构 B 一门课程。涉及到操作:
- 顾客 A 的余额减少
- 培训机构 B 所在的余额增加。
- 插入一条交易信息的操作。
对于第二个操作,当有许多人同时购买时并发度就较高,出现锁冲突的情况也较高。所以将操作 2 放置一个事务的最后就更好。
当有时并发度过大时,我们会发现一种现象 CPU 的使用率接近 100%,但事务执行数量却很少。这就可能出现了死锁。
死锁的检查
当并发系统中不同的线程出现循环的资源依赖,等待别的线程释放资源时,就会让涉及的线程处于一直等待的情况。这就称为死锁。
如上图中,事务 A 对id =1 的所在行,加入了行锁。等待 id=2 的行锁。事务 B 对 id = 2 的行,加入了行锁。等待 id=1 的行锁。事务 A,B 等待对方资源的释放。
如何解决死锁
方式 一: 设置死锁的等待时间 innodb_lock_wait_timeout
还是 sync_test 这张表,模拟简单的锁等待情况,注意这里并不是死锁。开启两个事务 A,B. 同时对 id=1 这行进行更新。
事务 A 更新操作:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update sync_test set name="dead_lock_test" where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
事务 B 更新操作:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update sync_test set name="dead_lock_test2" where id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
可以看到事务 B 抛出了死锁等待的错误。
设置等待时间的问题
在 InnoDB 中,MySQL 默认的死锁等待时间是 50s. 意味着在出现死锁后,被锁住的线程要过 50s 被能退出,这对于在线服务说,等待时间过长。但如果把值设置的过小,如果是像上述例子这样是简单的锁等待呢,并不是死锁怎么办,就会出现误伤的情况。
方式二:发起死锁检测,发现死锁后,主动回滚某个事务,让其他事务继续执行。
MySQL 中默认就是打开状态,能够快速发现死锁的情况。
set innodb_deadlock_detect=on
事务 A,B 互相依赖,造成死锁的例子:
开启事务 A:
mysql> begin;
mysql> update sync_test set name="dead_lock_test1" where id = 1;
开启事务 A:
mysql> begin;
mysql> update sync_test set name="dead_lock_test3" where id = 3;
トランザクションAを続行します。
mysql> update sync_test set name="dead_lock_test3_1" where id = 3;
# 会出现阻塞的情况
トランザクションBを続行します。
mysql> update sync_test set name="dead_lock_test1_2" where id = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
Aは正常に実行されたトランザクションを、キャンセルする場合は、この時点でブロックされました。
しかし、デッドロックの検出も、デッドロックで追加負担、トランザクションがロックされている時はいつでも、それは、スレッドが他の人をロックし、そのためにしていない依存し、最終的には待機ループがあるかどうかを判断参照する必要があります。すべてのトランザクションが同じ行のシーン、それを更新しますか?それぞれの新しいスレッドがブロックされ、そのため追加のデッドロックにつながったのと判断されることはありません、これは複雑さはO(n)の操作での時間です。同時に同じ行を更新するために、1000件の同時スレッドがあると仮定し、その後、デッドロック検出動作1000×1000 = 100万この大きさです。
だから、頻繁に大きなテーブルによって複雑更新のために、デッドロック検出は、CPUを大量に消費するためにつながります。
デッドロック検出の損失を回避する方法
方法1:ビジネスはデッドロックを保証するものではありません場合は、デッドロックが一時的にチェックをオフにすることができます。
そこにロールバックデッドロックした後、デッドロックのビジネス設計などの深刻な問題ではない、と何の問題が発生しないので、もう一度やり直してくださいしかし、これは一定のリスクがあります。しかし、デッドロック検出、発生する可能性のある状況のうちに多くの時間をオフにします。
方法2:同時実行制御。
あなたは、このような、その後のアップデートで10スレッドの唯一最大の、非常に低コストのデッドロック検出同時に同じラインとして、並行処理の量をコントロールすることができれば、彼らはこの問題は発生しません。具体的には、より多くの同時実行制御を行っているクライアントが、アプリケーションクライアントは、制御することはできません。データベース・サーバで同時実行制御ので、ミドルウェアも考慮することができるならばミドルウェアで実装。
方法3:デッドロックの可能性を減らします
統計線構造は、構造を蓄積し、複数の行に分割します。たとえば、10行の行の解体前に教育機関の量は、総収入は、データの10行の合計に相当します。オリジナルのロック衝突確率は、このようにCPUのデッドロック検出の消費量を削減、1/10になるように。しかし、行の部分で0になり、コードは特別な処理を必要とします。
概要
この記事では、今度は世界的なロック、テーブルレベルのロックと行ロックの概念を導入しました。
グローバルロックのために、RRレベルとMVCCの助けを借りて、InnoDBエンジンを使用して、あなたは同僚は、バックアップのデータを更新させることができます。
データベースハングその結果、テーブルレベルのロック、テーブル構造のホットテーブルを更新するための時間、状況MDL書き込みミューテックスロックに注意を払う、ため。
ロック競合を低減する行レベルのロック、二相ロック・プロトコルの使用の合理化のため。有料デッドロックの状況に注意を、適切な手段を取るためにデッドロック検出。