このサイトのMySQLストレージエンジンは「高速」という理由でMyISAMを使っています。
ですが適切なチューニングを行えばInnoDBは遅くないですし、何よりMyISAMよりも安全なはず。運用中のDBを弄るのはリスクもありますが、今後の為にInnoDB化します。
1.事前準備編
まずはmysqltunerで現状のパフォーマンスを確認します。
# mysqltuner -------- Performance Metrics ------------------------------------------------- [--] Up for: 29d 16h 40m 2s (1M q [0.566 qps], 44K conn, TX: 5B, RX: 499M) [--] Reads / Writes: 83% / 17% [--] Total buffers: 60.0M global + 2.9M per thread (12 max threads) [OK] Maximum possible memory usage: 94.5M (9% of installed RAM) [OK] Slow queries: 0% (2/1M) [OK] Highest usage of available connections: 83% (10/12) [OK] Key buffer size / total MyISAM indexes: 8.0M/458.0K [OK] Key buffer hit rate: 99.9% (11M cached / 12K reads) [OK] Query cache efficiency: 52.9% (591K cached / 1M selects) [OK] Query cache prunes per day: 11 [OK] Sorts requiring temporary tables: 0% (0 temp sorts / 100K sorts) [!!] Temporary tables created on disk: 43% (68K on disk / 157K total) [OK] Thread cache hit rate: 99% (10 created / 44K connections) [!!] Table cache hit rate: 2% (34 open / 1K opened) [OK] Open file limit used: 6% (67/1K) [OK] Table locks acquired immediately: 99% (645K immediate / 646K locks)
apacheベンチも実行しときます。(※WP Super Cacheを無効化した検証環境の実施結果)
# ab -n 1000 -c 10 https://localhost/ Requests per second: 14.01 [#/sec] (mean) Time per request: 713.914 [ms] (mean) Time per request: 71.391 [ms] (mean, across all concurrent requests) Transfer rate: 150.15 [Kbytes/sec] received
次にmysqlにログインしてWordPress用のテーブル名を確認します。
# mysql -uroot -p
mysql>use wp_wordpress;
mysql> select
table_name, engine,TABLE_COLLATION
from information_schema.tables
where table_schema=database()
order by (table_name) desc;
+-------------------------+------+---------------+
|table_name |engine|TABLE_COLLATION|
+-------------------------+------+---------------+
|wp_users |MyISAM|utf8_general_ci|
|wp_usermeta |MyISAM|utf8_general_ci|
|wp_term_taxonomy |MyISAM|utf8_general_ci|
|wp_term_relationships |MyISAM|utf8_general_ci|
|wp_terms |MyISAM|utf8_general_ci|
|wp_termmeta |MyISAM|utf8_general_ci|
|wp_site_cache |MyISAM|utf8_general_ci|
|wp_posts |MyISAM|utf8_general_ci|
|wp_postmeta |MyISAM|utf8_general_ci|
|wp_options |MyISAM|utf8_general_ci|
|wp_media_file_manager_log|MyISAM|utf8_unicode_ci|
|wp_links |MyISAM|utf8_general_ci|
|wp_comments |MyISAM|utf8_general_ci|
|wp_commentmeta |MyISAM|utf8_general_ci|
+-------------------------+------+---------------+
14 rows in set (0.00 sec)
WordPressのストレージエンジンをMyISAMで行くと決めた時からメモリ節約のためInnoDBは無効化していました。InnoDBを再有効化+最適化するには、InnoDBログファイルを再作成する必要があるのでファイルを削除します。
# ll -h /var/lib/mysql/ total 21M -rw-rw---- 1 mysql mysql 10M Jan 15 2015 ibdata1 -rw-rw---- 1 mysql mysql 5.0M Jan 15 2015 ib_logfile0 -rw-rw---- 1 mysql mysql 5.0M Jan 1 2015 ib_logfile1 drwx------ 2 mysql mysql 4.0K Nov 8 14:49 mysql srwxrwxrwx 1 mysql mysql 0 Feb 11 18:37 mysql.sock drwx------ 2 mysql mysql 4.0K Mar 12 03:52 wp_wordpress # rm -f /var/lib/mysql/ib_* # ll -h /var/lib/mysql/ total 10M -rw-rw---- 1 mysql mysql 10M Jan 15 2015 ibdata1 drwx------ 2 mysql mysql 4.0K Nov 8 14:49 mysql srwxrwxrwx 1 mysql mysql 0 Feb 11 18:37 mysql.sock drwx------ 2 mysql mysql 4.0K Mar 12 03:52 wp_wordpress
2.InnoDBを有効化する
まずはmy.cnfのInnoDB無効化設定をコメントアウトしInnoDBの初期設定を追加します。
# vi /etc/my.cnf
- skip-innodb
+ #skip-innodb
+ innodb_data_file_path = ibdata1:64M:autoextend
+ innodb_buffer_pool_size = 20M
+ innodb_file_per_table
+ innodb_autoextend_increment = 32
+ innodb_additional_mem_pool_size = 4M
+ innodb_log_buffer_size = 8M
+ innodb_log_file_size = 16M
+ innodb_flush_log_at_trx_commit = 2
mysqlを再起動してInnoDBを有効に出来るか、起動時に変なエラーが無いか確認します。
# service mysqld restart Stopping mysqld: [ OK ] Starting mysqld: [ OK ] # tail -n 30 /var/log/mysqld.log Version: '5.1.73' socket: '/var/lib/mysql/mysql.sock' port: 3306 Source distribution 160312 11:36:19 [Note] /usr/libexec/mysqld: Normal shutdown 160312 11:36:19 [Note] Event Scheduler: Purging the queue. 0 events 160312 11:36:19 InnoDB: Starting shutdown... 160312 11:36:24 InnoDB: Shutdown completed; log sequence number 0 44233 160312 11:36:24 [Note] /usr/libexec/mysqld: Shutdown complete 160312 11:36:24 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended 160312 11:36:25 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql 160312 11:36:25 InnoDB: Initializing buffer pool, size = 20.0M 160312 11:36:25 InnoDB: Completed initialization of buffer pool InnoDB: The first specified data file ./ibdata1 did not exist: InnoDB: a new database to be created! 160312 11:36:25 InnoDB: Setting file ./ibdata1 size to 64 MB InnoDB: Database physically writes the file full: wait... 160312 11:36:25 InnoDB: Log file ./ib_logfile0 did not exist: new to be created InnoDB: Setting log file ./ib_logfile0 size to 16 MB InnoDB: Database physically writes the file full: wait... 160312 11:36:25 InnoDB: Log file ./ib_logfile1 did not exist: new to be created InnoDB: Setting log file ./ib_logfile1 size to 16 MB InnoDB: Database physically writes the file full: wait... InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: Creating foreign key constraint system tables InnoDB: Foreign key constraint system tables created 160312 11:36:25 InnoDB: Started; log sequence number 0 0 160312 11:36:25 [Note] Event Scheduler: Loaded 0 events 160312 11:36:25 [Note] /usr/libexec/mysqld: ready for connections. Version: '5.1.73' socket: '/var/lib/mysql/mysql.sock' port: 3306 Source distribution
failの文字がないのでInnoDBは起動したっぽい。念のためmysqlのhave_innodbを参照して確認します。
# mysql -uroot -pmysql> show variables like "have_inno%";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_innodb | YES |
+---------------+-------+
1 row in set (0.00 sec)
Yesになっているのでバッチリです。
3.WordPressのテーブルをInnoDBに変換する
あとはmysqlにログインし「ALTER TABLE テーブル名 engine=InnoDB;」を実行するだけです。
DBの静止状態を作るためにservice httpd stopでhttpdを止めてから実行するつもりでしたが、ついうっかり停止せずやってしまいました。問題なかったので結果オーライです。
# mysql -uroot -puse wp_wordpress;
ALTER TABLE wp_users engine=InnoDB;
ALTER TABLE wp_usermeta engine=InnoDB;
ALTER TABLE wp_term_taxonomy engine=InnoDB;
ALTER TABLE wp_term_relationships engine=InnoDB;
ALTER TABLE wp_terms engine=InnoDB;
ALTER TABLE wp_termmeta engine=InnoDB;
ALTER TABLE wp_site_cache engine=InnoDB;
ALTER TABLE wp_posts engine=InnoDB;
ALTER TABLE wp_postmeta engine=InnoDB;
ALTER TABLE wp_options engine=InnoDB;
ALTER TABLE wp_media_file_manager_log engine=InnoDB;
ALTER TABLE wp_links engine=InnoDB;
ALTER TABLE wp_comments engine=InnoDB;
ALTER TABLE wp_commentmeta engine=InnoDB;
mysql> select
table_name, engine,TABLE_COLLATION
from information_schema.tables
where table_schema=database()
order by (table_name) desc;
+-------------------------+------+---------------+
|table_name |engine|TABLE_COLLATION|
+-------------------------+------+---------------+
|wp_users |InnoDB|utf8_general_ci|
|wp_usermeta |InnoDB|utf8_general_ci|
|wp_term_taxonomy |InnoDB|utf8_general_ci|
|wp_term_relationships |InnoDB|utf8_general_ci|
|wp_terms |InnoDB|utf8_general_ci|
|wp_termmeta |InnoDB|utf8_general_ci|
|wp_site_cache |InnoDB|utf8_general_ci|
|wp_posts |InnoDB|utf8_general_ci|
|wp_postmeta |InnoDB|utf8_general_ci|
|wp_options |InnoDB|utf8_general_ci|
|wp_media_file_manager_log|InnoDB|utf8_unicode_ci|
|wp_links |InnoDB|utf8_general_ci|
|wp_comments |InnoDB|utf8_general_ci|
|wp_commentmeta |InnoDB|utf8_general_ci|
+-------------------------+------+---------------+
14 rows in set (0.00 sec)
InnoDB化できました。
早速ベンチを取ります。(※WP Super Cacheを無効化した検証環境の実施結果)
# ab -n 1000 -c 10 https://localhost/ Requests per second: 14.15 [#/sec] (mean) Time per request: 706.741 [ms] (mean) Time per request: 70.674 [ms] (mean, across all concurrent requests) Transfer rate: 151.45 [Kbytes/sec] received
MyISAMの時は14.01[#/sec]でしたので、少なくとも遅くなっていないようです。成功かな?
4.InnoDB用のパラメータチューニング
このままではMyISAMとInnoDB両方のキャッシュを確保していることになるので無駄なメモリがあります。1GBでやり繰りするためは少しでもメモリを節約したいのでMyISAM用の設定を削除します。取りあえず今のところ設定しているmy.cnfのパラメータはこんなところ。
# cat /etc/my.cnf [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 character-set-server=utf8 skip-character-set-client-handshake default-storage-engine=InnoDB skip-name-resolve skip-external-locking #innoDB turning innodb_data_file_path = ibdata1:64M:autoextend innodb_log_file_size = 16M innodb_buffer_pool_size = 20M innodb_file_per_table innodb_autoextend_increment = 16 innodb_additional_mem_pool_size = 4M innodb_log_buffer_size = 4M innodb_flush_log_at_trx_commit = 2 skip_innodb_doublewrite query_cache_size=20M table_open_cache = 64 tmp_table_size=16M max_heap_table_size=16M max_connections = 12 thread_cache_size = 20 max_allowed_packet = 1M sort_buffer_size = 512k read_buffer_size = 512k read_rnd_buffer_size = 1M key_buffer_size = 2M #myisam_sort_buffer_size = 1M wait_timeout = 300
ついでにmysqltunerの結果も。
# mysqltuner -------- Storage Engine Statistics ------------------------------------------- [--] Status: -Archive -BDB -Federated +InnoDB -ISAM -NDBCluster [--] Data in InnoDB tables: 3M (Tables: 14) [!!] Total fragmented tables: 2 -------- Security Recommendations ------------------------------------------- [OK] All database users have passwords assigned -------- Performance Metrics ------------------------------------------------- [--] Up for: 1h 3m 16s (7K q [1.870 qps], 262 conn, TX: 26M, RX: 3M) [--] Reads / Writes: 79% / 21% [--] Total buffers: 66.0M global + 2.4M per thread (12 max threads) [OK] Maximum possible memory usage: 94.5M (9% of installed RAM) [OK] Slow queries: 0% (0/7K) [OK] Highest usage of available connections: 25% (3/12) [OK] Key buffer size / total MyISAM indexes: 2.0M/89.0K [OK] Query cache efficiency: 40.2% (2K cached / 5K selects) [OK] Query cache prunes per day: 0 [OK] Sorts requiring temporary tables: 0% (0 temp sorts / 540 sorts) [!!] Temporary tables created on disk: 45% (408 on disk / 904 total) [OK] Thread cache hit rate: 98% (3 created / 262 connections) [OK] Table cache hit rate: 84% (38 open / 45 opened) [OK] Open file limit used: 4% (46/1K) [OK] Table locks acquired immediately: 100% (3K immediate / 3K locks) [OK] InnoDB data size / buffer pool: 3.5M/20.0M
結果はMyISAMの時と変わらず、概ね良好でした。何故かTotal fragmented tablesの値が2から減りませんが、InnoDB テーブルのデフラグメント化を試しても変わらなかったので諦めます。
InnoDB化は安全性の確保が目的でしたが、MySQL5.6へバージョンアップすることによる高速化の布石でもあったりします。既に検証環境で試していますが、MySQL5.6にしても遅くなる結果しか出ていないため実装 & 記事化はしばらくお預けになりそうです。