web-dev-qa-db-ja.com

mysqlがLOAD DATA INFILEステートメントをプロファイリングする際の「システムロック」とはどういう意味ですか?

LOAD DATA INFILEを使用してinnodbに挿入された2M行は7.5分かかり、プロファイリングはその時間の99%が"システムロック"であることを示しています。

これは何か役に立つことを教えてくれますか?

   mysql> set profiling=1;
   Query OK, 0 rows affected (0.00 sec)

   mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
   Query OK, 1964807 rows affected, 8 warnings (7 min 27.35 sec)
   Records: 1964806  Deleted: 1  Skipped: 0  Warnings: 8

   mysql> show profile for query 1;
   +------------------------------+------------+
   | Status                       | Duration   |
   +------------------------------+------------+
   | starting                     |   0.000206 |
   | checking permissions         |   0.000015 |
   | Opening tables               |   0.000034 |
   | System lock                  | 447.327523 |
   | Waiting for query cache lock |   0.000352 |
   | query end                    |   0.000011 |
   | closing tables               |   0.000014 |
   | freeing items                |   0.000033 |
   | logging slow query           |   0.000007 |
   | logging slow query           |   0.000006 |
   | cleaning up                  |   0.000006 |
   +------------------------------+------------+
   11 rows in set (0.02 sec)
6
David Parks

MySQL Documentation for General Thread States によると==

スレッドは、テーブルの内部または外部システムロックを要求するか、または待機しています。この状態の原因が外部ロックのリクエストであり、同じMyISAMテーブルにアクセスしている複数のmysqldサーバーを使用していない場合は、-skip-external-lockingオプションを使用して外部システムロックを無効にできます。ただし、外部ロックはデフォルトで無効になっているため、このオプションは効果がない可能性があります。 SHOW PROFILEの場合、この状態は、スレッドがロックを要求している(それを待っていない)ことを意味します。

InnoDBは行レベルのロックを行うため、これは驚くべきことではありません。さらに、 gen_clust_index(a.k.a. Clustered Index) では、ある時点で主キーの共有ロックと排他ロックが発生します。

5
RolandoMySQLDBA

Mysql_load()関数はopen_and_lock_tables()関数を呼び出して、LOAD DATAステートメントで言及されたテーブルをロックします。

MySQLはテーブルに排他ロックを取得するため、テーブルにデータを非常に迅速にロードできます。 LOAD DATAプロセスにはほとんどオーバーヘッドがありません。最低限の解析が行われて機能します。

CONCURRENTオプションはMyISAMテーブルにのみ影響します。InnoDBテーブルにロードしている場合、同時アクセスは許可されません。

システムロックに非常に時間がかかった理由は、実際のデータロードがそのステップのタイミングにまとめられたためです。プロファイラーは、fencepostsの間の時間を測定することで機能します。つまり、エントリー時間は、インストルメント化されたユーザー関数ごとに記録されます。 mysql_lock_tables()関数はmysql_load()内から呼び出されますが、mysql_load()はインストルメント化されていないため、経過時間はシステムロックで始まり、クエリキャッシュロックである次のフェンスポストで終わります。

1.96百万行のデータロードには約447秒かかりました。ロードは計測されていないため、実際のロック時間のオーバーヘッドとロード時間を分離する方法はありません。

6