web-dev-qa-db-ja.com

MySQLはディスク上に一時テーブルを作成します。どうすれば停止できますか?

ユーザーが現在遅いと感じるサイト(Moodle)を実行しています。ディスクに一時テーブルを作成するMySQLに問題を追跡したと思います。 Mysql Workbenchサーバー管理で変数_created_tmp_disk_tables_を監視していますが、その数は約50テーブル/秒で増加します。 1日の使用後、_created_tmp_disk_tables_は> 100kです。また、メモリが解放されていないようです。システムがほとんど使用できなくなり、MySQLを再起動する必要があるまで、使用量は増加し続けます。ほぼ毎日再起動する必要があり、使用可能なメモリの約30〜35%を使用して、1日を80%で終了します。

データベースにblobがなく、クエリを制御することもできないため、クエリを最適化することはできません。 Percona Confirguration Wizard を使用して構成ファイルを生成しましたが、my.iniでも問題を解決できませんでした。

ご質問

  1. MySQLがディスクに一時テーブルを作成しないようにするには、何を変更すればよいですか?変更する必要がある設定はありますか?もっとメモリを投げる必要がありますか?

  2. MySQLがメモリを使い果たすのを防ぐにはどうすればよいですか?

編集する

_slow_queries_ログを有効にしたところ、クエリSELECT GET_LOCK()のログが遅いことがわかりました。簡単な検索により、PHP=構成(_mysqli.allow_persistent = ON_)で永続的な接続を許可していたことがわかりました。これをオフにしました。これにより、MySQLがメモリを消費する速度が低下しました。ただし、一時テーブル。

_key_buffer size_が十分に大きいことも確認しました。変数_key_writes_を調べました。これはゼロでなければなりません。そうでない場合は、_key_buffer_size_を増やします。_key_reads_と_key_writes_がゼロであるため、_key_buffer_size_は十分に大きいと想定しています。

Created_tmp_disk_tablesを増やすとテーブルがメモリに収まらない可能性があるため、_tmp_table_size_および_max-heap-table-size_を1024Mに増やしました。これはそれを解決しませんでした。

参照: http://www.mysqlperformanceblog.com/2007/08/16/how-much-overhead-is-caused-by-on-disk-temporary-tables/

編集2

SHOW GLOBAL STATUS出力に毎秒多くの_sort_merge_passes_が表示される場合は、_sort_buffer_size_値を増やすことを検討できます。 1時間に2つの_sort_merge_passes_があったので、_sort_buffer_size_は十分な大きさであると考えています。

参照:_sort_buffer_size_のMysqlマニュアル

編集3

@RolandoMySQLDBAの提案に従って、ソートおよび結合バッファーを変更しました。結果は下の表に表示されていますが、_created_tmp_tables_on_disk_はまだ高いと思います。値を変更してmysqlサーバーを再起動し、1日(8時間)後に_created_tmp_tables_on_disk_を確認して平均を計算しました。他に何か提案はありますか?なんらかのコンテナの中に収まらないものがあるように見えますが、それが何かはわかりません。

_+---------------------+-------------+-------------+--------------------+
| Tmp_table_size,     | Sort_buffer | Join_buffer | No of created      |
| max_heap_table_size |             |             | tmp_tables on disk |
+---------------------+-------------+-------------+--------------------+
| 125M                | 256K        | 256K        |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 512K        | 512K        |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 1M          | 1M          |  100k/h            |
+---------------------+-------------+-------------+--------------------+
| 125M                | 4M          | 4M          |  100k/h            |
+---------------------+-------------+-------------+--------------------+   
_



これは私の設定です:

_+-----------------------+-----------------------+
|DATABASE SERVER        |WEB SERVER             |
+-----------------------+-----------------------+
|Windows Server 2008 R2 |Windows Server 2008 R2 |
+-----------------------+-----------------------+
|MySQL 5.1.48           |IIS 7.5                |
+-----------------------+-----------------------+
|4 Core CPU             |4 Core CPU             |
+-----------------------+-----------------------+
|4GB RAM                |8GB RAM                |
+-----------------------+-----------------------+
_

追加情報

_+--------------------+---------+
|PARAM               |VALUE    |
+--------------------+---------+
|Num of tables in Db |361      |
+--------------------+---------+
|Size of database    |2.5G     |
+--------------------+---------+
|Database engine     |InnoDB   |
+--------------------+---------+
|Read/write ratio    |3.5      |
|(Innodb_data_read/  |         |
|innodb_data_written)|         |
+--------------------+---------+
|Avg table size      |15k rows |
+--------------------+---------+
|Max table size      |744k rows|
+--------------------+---------+
_

この設定は私に与えられたので、私はそれに対する制御を制限しています。 WebサーバーはCPUをほとんど使用しておらず、RAMなので、そのマシンをボトルネックとして除外しました。MySQL設定の大部分は、構成自動生成ツールに由来しています。

私は、PerfMonを使用して数日間、システムを監視しました。このことから、ディスクにスワップしているのはOSではないと結論付けました。

_My.ini

[client]
port=3306
[mysql]
default-character-set=utf8

[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.1/"
datadir="D:/DBs/Data/"
default-character-set=utf8
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=125
query_cache_size=350M
table_cache=1520
tmp_table_size=125M
table-definition-cache= 1024
max-heap-table-size= 32M
thread_cache_size=38

MyISAM Specific options
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=125M
key_buffer_size=55M
read_buffer_size=1024K
read_rnd_buffer_size=256K
sort_buffer_size=1024K
join_buffer_size=1024K


INNODB Specific options
innodb_data_home_dir="D:/DBs/"
innodb_additional_mem_pool_size=32M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=16M
innodb_buffer_pool_size=2G
innodb_log_file_size=407M
innodb_thread_concurrency=8
_
29
user30431

my.iniを見ると、2つの提案があります

提案#1

my.iniの次の設定を増やします

sort_buffer_size=4M
join_buffer_size=4M

これにより、一部の結合と並べ替えがメモリに残ります。もちろん、JOINまたはORDER BY4Mより多く必要になると、MyISAMテーブルとしてディスクにページングされます。

root@localhostとしてログインできない場合は、mysqlを再起動してください

C:\> net stop mysql
C:\> net start mysql

Root @ localhostとしてログインできる場合、これらの設定を使用するためにmysqlを再起動する必要はありません。

これをMySQLクライアントで実行するだけです。

SET @FourMegs = 1024 * 1024 * 4;
SET GLOBAL sort_buffer_size = @FourMegs;
SET GLOBAL join_buffer_size = @FourMegs;

提案#2

データはドライブD:にあるため、ドライブC:にディスクI/Oがある可能性があります。

このクエリを実行してください:

mysql> show variables like 'tmpdir';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tmpdir        | C:\Windows\TEMP |
+---------------+-----------------+
1 row in set (0.00 sec)

デフォルトでmysqlをデスクトップで実行しているため、一時テーブルはドライブC:に書き込まれています。ドライブDがドライブC:より優れたディスクである場合、おそらくD:tmpdir を設定することにより、一時テーブルをドライブmy.iniにマップできます。続く:

tmpdir="D:/DBs/"

tmpdir は動的変数ではないため、mysqlを再起動する必要があります。

試してみる !!!

2013-11-29 10:09 EST更新

提案#3

MySQLがWindowsで実行されていて、コアパッケージのクエリに触れられないという事実を考えると、私は2つのアイデアを一緒に実行する必要があると考えています。

アイデア#1:データベースをLinuxマシンに移動する

あなたはできるはずです

  • Linuxマシンのセットアップ
  • LinuxマシンにMySQLをインストールする
  • WindowsでMySQLのバイナリログを有効にする
  • mysqldumpでデータベースをテキストSQLファイルに
  • Linuxで実行されているMySQLにSQLファイルをロードする
  • MySQL/WindowsからMySQL/Linuxへのレプリケーションのセットアップ

アイデア#2:Linuxマシンを指すようにMoodleを再構成する

MoodleはそもそもLAMP用に設計されました。 localhostではなくLinuxマシンを指すように設定ファイルを変更するだけです。

MySQLの設定に関する古いMoodle 2.3ドキュメントへのリンクは次のとおりです: http://docs.moodle.org/23/en/Installing_Moodle#Create_an_empty_database

最新のドキュメントも入手できると思います。

データベースをLinuxに移動するポイントは何ですか???

これは一時テーブルの状況にどのように役立ちますか?

次に、一時テーブルのターゲットフォルダとしてRAM diskを設定することをお勧めします

一時テーブルの作成は引き続き行われますが、ディスクではなくRAMに書き込まれます。ディスクI/Oを減らします。

UPDATE 2013-11-29 11:24 EST

提案#4

高速RAID-0ディスク(32+ GB)でSUGGESTION#2を再検討し、ドライブT:(T for Temp)として構成することをお勧めします。そのようなディスクをインストールした後、これをmy.iniに追加します。

[mysqld]
tmpdir="T:\"

MySQLの再起動が必要です。

net stop mysql
net start mysql

ところで私はRAID-0を故意に言ったので、RAID-1、RAID-10よりも優れた書き込みパフォーマンスを得ることができます。 tmpテーブルディスクは、私が冗長にするものではありません。

@RaymondNijlandがコメントしているようにクエリを最適化しないと、一時テーブルの作成数を減らすことはできません。 SUGGESTION #3およびSUGGESTION #4は、一時テーブルの作成と一時テーブルI/Oの高速化を唯一の代替手段として提供します。

16
RolandoMySQLDBA

私は完全性のためにここで自分の質問に答えます

@RolandoMySQLDBAを選択します。実際に問題を解決していなくても、最もヒントが得られたためです。

以下は私の調査結果です

結論

Windows上のMySQLは、多くの一時テーブルを作成し、構成ファイルの内容を変更してMySQLを調整するだけでは役に立ちませんでした。

細部

この表は、クエリを実行する前にmy.iniでそれぞれ変更したパラメータの詳細を示しています。 MySQLは各テストの間に再起動されました。

元の質問で見つかったmy.iniをテンプレートとして使用し、次の表に従ってパラメーターの値を1つずつ変更しました。

私は JMeter を使用して、10回繰り返される100の同時Webリクエスト(使用方法を表す)を生成しました。したがって、各Testは合計で1000件のリクエストで構成されていました。これにより、後続のデータベース呼び出しが発生しました。これは、MySQLが変更した構成パラメータに関係なく、多くの一時テーブルを作成することを示しています。

+----+------------+-------+---------------+------------+
|Test|Parameter   |Value  |NumOfTempTables|Db Max Conn |
+----+------------+-------+---------------+------------+
| 1  |key_buffer_ | 25M   | 30682         | 29         |
|    |size        |       |               |            | 
+----+------------+-------+---------------+------------+
| 2  |key_buffer_ | 55M   | 30793         | 29         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 3  |key_buffer_ | 100M  | 30666         | 28         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 4  |key_buffer_ | 125M  | 30593         | 24         |
|    |size        |       |               |            | 
+----+------------+-------+---------------+------------+
| 5  |query_cache_| 100M  | 30627         | 32         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 6  |query_cache_| 250M  | 30761         | 26         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 7  |query_cache_| 500M  | 30864         | 83*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 8  |query_cache_| 1G    | 30706         | 75*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 9  |tmp_table_  | 125M  | 30724         | 31         |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 10 |tmp_table_  | 250M  | 30689         | 90*        |
|    |size        |       |               |            |
+----+------------+-------+---------------+------------+
| 11 |tmp_table_  | 500M  | 30792         | 28         |
|    |size        |       |               |            |  
+----+------------+-------+---------------+------------+
| 12 |Sort_buffer&| 256K  | 30754         | 28         |
|    |Join_buffer |       |               |            |
+----+------------+-------+---------------+------------+
| 13 |Sort_buffer&| 512K  | 30788         | 30         |
|    |Join_buffer |       |               |            | 
+----+------------+-------+---------------+------------+
| 14 |Sort_buffer&| 1M    | 30788         | 28         |
|    |Join_buffer |       |               |            | 
+----+------------+-------+---------------+------------+
| 15 |Sort_buffer&| 4M    | 30642         | 35         |
|    |Join_buffer |       |               |            |
+----+------------+-------+---------------+------------+
| 16 |innodb-     | 1G    | 30695         | 33         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            |
+----+------------+-------+---------------+------------+
| 17 |innodb-     | 2G    | 30791         | 28         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            | 
+----+------------+-------+---------------+------------+
| 18 |innodb-     | 3G    | 30719         | 34         |
|    |buffer-     |       |               |            |
|    |pool-size   |       |               |            |  
+----+------------+-------+---------------+------------+

* 3回の実行の平均

以下の画像は、データベースサーバーがさまざまな構成に必要なメモリとCPUの量を示しています。黒い線は最小値と最大値を示し、青いバーは開始値と終了値を示します。最大メモリは4096M質問に示されています。

Memory UsageCPU Usage

13
user30431

インメモリ一時テーブルサイズが最大ヒープテーブルサイズ変数によって制限されているかどうかも確認する必要があります。

メモリ内一時テーブル にMEMORYストレージエンジンを使用する場合、MySQLはメモリ内一時テーブルが大きくなりすぎるとディスク上のテーブルに自動的に変換します。

一時テーブルの作成に必要なスペースがtmp_table_sizeまたはmax_heap_table_size、MySQLはサーバーのtmpdirディレクトリにディスクベースのテーブルを作成します。インメモリ一時テーブルの最大サイズは、tmp_table_sizeまたはmax_heap_table_size値、どちらか小さい方。

0
martoncsukas