35

これはかなり単純な問題です。テーブルへのデータの挿入は、挿入クエリに数秒かかる数回を除いて、通常は正常に機能します。(データを一括挿入しようとしているわけではありません。) そこで、挿入プロセスのシミュレーションをセットアップして、挿入クエリの実行に 2 秒以上かかる場合がある理由を調べました。Joshua は、インデックス ファイルが調整されている可能性があることを示唆しました。ID (主キー フィールド) を削除しましたが、それでも遅延が発生します。

MyISAM テーブルがあります: daniel_test_insert(このテーブルは最初は完全に空です):

create table if not exists daniel_test_insert ( 
    id int unsigned auto_increment not null, 
    value_str varchar(255) not null default '', 
    value_int int unsigned default 0 not null, 
    primary key (id) 
)

そこにデータを挿入すると、挿入クエリの実行に 2 秒以上かかることがあります。 このテーブルには読み取りはありません。単一のスレッド化されたプログラムによるシリアルの書き込みのみです。

まったく同じクエリを 100,000 回実行して、クエリに時間がかかる理由を見つけました。これまでのところ、それはランダムに発生しているようです。

たとえば、このクエリには 4.194 秒かかりました (挿入には非常に長い時間)。

Query: INSERT INTO daniel_test_insert SET value_int=12345, value_str='afjdaldjsf aljsdfl ajsdfljadfjalsdj fajd as f' - ran for 4.194 seconds
status               | duration | cpu_user  | cpu_system | context_voluntary | context_involuntary | page_faults_minor
starting             | 0.000042 | 0.000000  | 0.000000   | 0                 | 0                   | 0                
checking permissions | 0.000024 | 0.000000  | 0.000000   | 0                 | 0                   | 0                
Opening tables       | 0.000024 | 0.001000  | 0.000000   | 0                 | 0                   | 0                
System lock          | 0.000022 | 0.000000  | 0.000000   | 0                 | 0                   | 0                
Table lock           | 0.000020 | 0.000000  | 0.000000   | 0                 | 0                   | 0                
init                 | 0.000029 | 0.000000  | 0.000000   | 1                 | 0                   | 0                
update               | 4.067331 | 12.151152 | 5.298194   | 204894            | 18806               | 477995           
end                  | 0.000094 | 0.000000  | 0.000000   | 8                 | 0                   | 0                
query end            | 0.000033 | 0.000000  | 0.000000   | 1                 | 0                   | 0                
freeing items        | 0.000030 | 0.000000  | 0.000000   | 1                 | 0                   | 0                
closing tables       | 0.125736 | 0.278958  | 0.072989   | 4294              | 604                 | 2301             
logging slow query   | 0.000099 | 0.000000  | 0.000000   | 1                 | 0                   | 0                
logging slow query   | 0.000102 | 0.000000  | 0.000000   | 7                 | 0                   | 0                
cleaning up          | 0.000035 | 0.000000  | 0.000000   | 7                 | 0                   | 0

(これは SHOW PROFILE コマンドの省略版です。すべてゼロの列を削除しました。)

現在、この更新プログラムには、信じられないほどの数のコンテキスト スイッチとマイナーなページ フォールトが含まれています。Opened_Tables は、このデータベースで 10 秒ごとに約 1 増加します (table_cache スペースが不足していません)。

統計:

  • MySQL 5.0.89

  • ハードウェア: 32 ギグの RAM / 8 コア @ 2.66GHz。RAID 10 SCSI ハードディスク (SCSI II???)

  • ハード ドライブと RAID コントローラを照会しました。エラーは報告されていません。CPU は約 50% アイドル状態です。

  • iostat -x 5 (ハードディスクの使用率が 10% 未満であると報告されます) 1 分間の負荷平均が約 10 であると報告されます (db マシンでは通常)

  • スワップ領域には 156k が使用されています (32 GB の RAM)

このパフォーマンスの遅れの原因を突き止めるのに途方に暮れています。これは、低負荷のスレーブでは発生せず、高負荷のマスターでのみ発生します。これは、メモリおよび innodb テーブルでも発生します。誰か提案はありますか?(これは本番システムなので、風変わりなものではありません!)

4

11 に答える 11

22

私のシステムでも同じ現象に気づきました。通常はミリ秒かかるクエリが、突然 1 ~ 2 秒かかるようになります。私のケースはすべて単純な単一テーブルの INSERT/UPDATE/REPLACE ステートメントです --- SELECT ではありません。ロード、ロック、またはスレッドのビルドアップは明らかではありません。

ダーティ ページの消去、ディスクへの変更のフラッシュ、または隠しミューテックスが原因ではないかと疑っていましたが、まだ絞り込んでいません。

こちらも除外

  • サーバーの負荷 -- 高負荷との相関関係なし
  • エンジン -- InnoDB/MyISAM/Memory で発生
  • MySQL Query Cache -- オンでもオフでも発生します
  • ログのローテーション -- イベントに相関関係なし

この時点で私が持っている他の唯一の観察は、複数のマシンで同じデータベースを実行しているという事実から導き出されたものです。負荷の高い読み取りアプリケーションを使用しているため、レプリケーションのある環境を使用しています。ほとんどの負荷はスレーブにあります。マスターに最小限の負荷がかかっている場合でも、現象がより多く発生することに気付きました。ロックの問題は見られませんが、(スレッド) 同時実行性に問題があるのは Innodb/Mysql でしょうか? スレーブでの更新はシングル スレッドであることを思い出してください。

MySQL バージョン 5.1.48

アップデート

私は私のケースの問題のリードを持っていると思います。一部のサーバーでは、他のサーバーよりもこの現象に気付きました。さまざまなサーバー間で何が違うのかを見て、微調整していると、MySQL innodb システム変数 innodb_flush_log_at_trx_commitにたどり着きました。

ドキュメントは少し読みにくいと思いましたがinnodb_flush_log_at_trx_commit、1、2、0 の値を取ることができます。

  • 1 の場合、ログ バッファはコミットごとにログ ファイルにフラッシュされ、ログ ファイルはコミットごとにディスクにフラッシュされます。
  • 2 の場合、ログ バッファはコミットごとにログ ファイルにフラッシュされ、ログ ファイルは約 1 ~ 2 秒ごとにディスクにフラッシュされます。
  • 0 の場合、ログ バッファは毎秒ログ ファイルにフラッシュされ、ログ ファイルは毎秒ディスクにフラッシュされます。

事実上、(1,2,0) の順序で、報告および文書化されているように、リスクの増加と引き換えにパフォーマンスが向上するはずです。

そうは言っても、 のサーバーは のサーバーよりinnodb_flush_log_at_trx_commit=0もパフォーマンスが悪い (つまり、「長い更新」が 10 ~ 100 倍多い) ことがわかりましたinnodb_flush_log_at_trx_commit=2。さらに、2に切り替えると、悪いインスタンスがすぐに改善されました(その場で変更できることに注意してください)。

それで、私の質問は、あなたの設定は何ですか?このパラメーターを非難しているわけではなく、そのコンテキストがこの問題に関連していることを強調していることに注意してください。

于 2010-11-09T22:38:25.900 に答える
1

400 (null ではない) 列を持つテーブルをもう 1 つ作成して、テストを再度実行できますか? 遅い挿入の数が増えた場合、MySQL がレコードの書き込みに時間を浪費していることを示している可能性があります。(それがどのように機能するかはわかりませんが、彼はより多くのブロックを割り当てているか、断片化を避けるために何かを移動している可能性があります....本当にわかりません)

于 2010-09-22T14:37:05.750 に答える
1

for ループを使用して 1 つの複数の挿入を使用している場合は、PHP の sleep("time in seconds") 関数を使用して、ループごとに休憩を取ってください。

于 2016-07-22T05:39:04.807 に答える
1

INNODB テーブルを使用してこの問題が発生しました。(そして、INNODB インデックスは、MYISAM よりも書き換えがさらに遅くなります)

他のいくつかのテーブルで他の複数のクエリを実行していると思われるため、問題は、MySQL がファイルのディスク書き込みを処理する必要があり、それらのファイルに追加のスペースを割り当てる必要があることです。

MYISAM テーブルを使用する場合は、使用することを強くお勧めします

LOAD DATA INFILE 'file-on-disk' INTO TABLE `tablename` 

指図; MYISAM はこれにより (主キーを使用しても) 驚くほど高速であり、ファイルは csv としてフォーマットでき、列名を指定できます (または自動インクリメント フィールドの値として NULL を指定できます)。

ここで MYSQL ドキュメントを表示します

于 2010-09-16T08:35:07.683 に答える
1

MySQL 5.1 にアップグレードしましたが、このイベント中にクエリ キャッシュが多くの「アイテムを解放しますか?」という問題になりました。スレッドの状態。次に、クエリ キャッシュを削除しました。

MySQL 5.1 にアップグレードするか、クエリ キャッシュを削除することで、この問題は解決しました。

参考までに、将来の読者へ。

-ダニエル

于 2010-12-09T23:02:31.390 に答える
1

まったく同じ問題に遭遇し、ここで報告しました: http://bugs.mysql.com/bug.php?id=62381

5.1.52 を使用していますが、まだ解決策がありません。このパフォーマンス ヒットを回避するために、QC をオフにする必要がある場合があります。

于 2011-09-22T10:28:38.577 に答える
1

最初のヒントは、自動コミット機能を無効にして、手動でコミットすることです。

LOCK TABLES a WRITE;
... DO INSERTS HERE
UNLOCK TABLES;

すべての INSERT ステートメントが完了した後、インデックス バッファーが 1 回だけディスクにフラッシュされるため、これによりパフォーマンスが向上します。通常、INSERT ステートメントと同じ数のインデックス バッファー フラッシュがあります。

しかし、おそらくあなたができる最善のことであり、アプリケーションでそれが可能な場合は、単一の選択で一括挿入を行います。

これは Vector Binding を介して行われ、これが最速の方法です。

Instead
of:
"INSERT INTO tableName values()"
DO
"INSERT INTO tableName values(),(),(),().......(n) " ,

ただし、このオプションは、使用している mysql ドライバーでパラメーター ベクターのバインディングが可能な場合にのみ検討してください。

それ以外の場合は、最初の可能性を考えて、1000 回の挿入ごとにテーブルをロックします。バッファ オーバーフローが発生するため、100k の挿入に対してロックしないでください。

于 2010-09-16T08:46:32.953 に答える
0

ディスクの動作が悪いかどうかを確認し、Windowsを使用している場合は、10,000個のファイルを作成するバッチcmdファイルを作成できます。

@echo OFF
FOR /L %%G IN (1, 1, 10000) DO TIME /T > out%%G.txt

test.cmdのように一時ディレクトリに保存します

/ E:ONパラメーターを指定してCMDを実行しているコマンド拡張機能を有効にします

CMD.exe /E:ON

次に、バッチを実行して、最初の出力ファイルと最後の出力ファイルの間の時間が秒または分で異なるかどうかを確認します。

Unix / Linuxでは、同様のシェルスクリプトを作成できます。

于 2010-09-27T15:55:54.230 に答える
0

Myisam Performance でこれを読んでください: http://adminlinux.blogspot.com/2010/05/mysql-allocating-memory-for-caches.html

検索する:

「The MyISAM key block size The key block size is important」(一重引用符を除く)、これが原因である可能性があります。5.1でこれらの問題のいくつかを修正したと思います

于 2010-09-21T19:49:12.817 に答える
0

ディスク サブシステムの統計を確認できますか? I/O が飽和していませんか? これは、内部 DB の作業がディスク/ログにフラッシュを行っているように思えます。

于 2010-09-24T15:10:43.230 に答える
0

ひょっとしたら、サーバーに SSD ドライブはありますか? 一部の SSD ドライブでは「スタダー」が発生し、症状を引き起こす可能性があります。

いずれにせよ、遅延が MySQL で発生しているのか、ディスク サブシステムで発生しているのかを調べてみます。

サーバーはどの OS で、MySQL データはどのファイル システムにありますか?

于 2010-10-02T05:29:42.700 に答える