Upload
mikiya-okuno
View
45.199
Download
11
Embed Size (px)
Citation preview
MySQL 5.6MySQL 5.6 新機能解説新機能解説
奥野 幹也@nippondanjimikiya (dot) okuno (at) gmail (dot) com
@ db tech showcase 2012
免責事項
● 本プレゼンテーションにおいて示されている見解は、私自身の見解であって、オラクル・コーポレーションの見解を必ずしも反映したものではありません。ご了承ください。
自己紹介
● MySQL サポートエンジニア– 2000 年にサン・マイクロシステムズ入社
● 主にハードウェアのサポートを担当– 2007 年に MySQL KK へ転職
● 気付くとまたサン・マイクロシステムズに・・・– 現在は日本オラクルに在席。– サポート一筋 12 年
● 日々のしごと– MySQL トラブルシューティング全般– Q&A 回答
など● ブログ
– 漢のコンピュータ道– http://nippondanji.blogspot.com/
MySQL 5.6新機能ダイジェスト
MySQL 5.6 リリース候補版登場!
● MySQL Connect 2012 において MySQL 5.6 リリース候補版( RC = Release Candidate )が発表された。
– MySQL Connect は Oracle OpenWorld と並んで US で開催されたイベント
● リリース候補版≒ Feature Fix!!– 約 200 の Worklog に対応– 機能は開発版( DRM = Development Milestone
Release )で徐々に追加するという開発モデル● MySQL 5.5GA (2010年 12 月)以来のメジャーアップ
デート– マイナーバージョンではありません。– 正式版( GA = General Availability )までしばらくお待ち
を!!
レプリケーション
● GTID – Global Transaction ID– スレーブの自動的な昇格が可能に!!
● クラッシュセーフなスレーブ● 遅延レプリケーション● mysqlbinlog コマンドによるバイナリログのバックアップ● スレーブが使用する NIC の指定● マルチスレッドスレーブ
– スレーブ SQL スレッドが複数のスレッドで実行可能に!!– DB 単位での並列処理
InnoDB
● インデックスの追加と削除がオンラインで可能に!!● FULLTEXT インデックスのサポート● .ibd ファイル(テーブル単位のデータファイル)のエクス
ポートとインポート– ファイルのコピー+ α の操作他のサーバーへ移行可能!!
● ページサイズの指定( 16KB→4KB/8KB/16KB )● インデックス統計情報の改善● START TRANSACTION READ ONLY● ログサイズの上限が増加( 4GB→512GB )● デッドロック検出機能の改善● CPU スケーラビリティの向上● バッファプールの内容を保存、再起動時に暖機運転● memcached インターフェイス
オプティマイザ
● サブクエリの高速化– semi-join最適化– FROM句のサブクエリの評価遅延
● EXPLAIN の改善– SELECT 以外の DML へ対応
● 各種アルゴリズムの改善– ORDER BY ... LIMIT の効率化– Batched Key Access Join– Index Condition Pushdown– Multi Range Read
● オプティマイザトレース
パーティショニング
● パーティションをテーブル同士で交換可能に● パーティション数の上限増加( 1024→8192 )● 明示的なパーティションの指定● テーブルロックの改善
– テーブルロックの対象がテーブル全体からパーティション単位に
その他
● セキュリティ関係● ジャイアントロックの解消● ホストキャッシュの参照● OpenGIS 対応● 小数点以下の秒への対応● ストアドルーチンにおけるエラーハンドリングの改善
– Diagnostic Area
参考:開発スピードアクセル全開ぶっちぎり!日本よ、これが MySQL 5.6 だッ!!http://nippondanji.blogspot.com/2012/10/mysql-56.html
時間の都合上すべてをお見せすることが
できません。
あまりにもたくさん目覚しい新機能があるからです!
レプリケーション
MySQL のレプリケーション
マスター スレーブ
ストレージエンジン
ストレージエンジン
バイナリログ リレーログ
接続スレッド
アプリケーション
スレーブ接続スレッド
I/Oスレッド
SQLスレッド
1. COMMIT
2. バイナ
リログ
更新3. テーブル
更新
4-1. send_ok
4-2. バイナリログ送信
5. リレーログ更新6. 更新の適用
MySQL のレプリケーション(つづき)
Master Slave
マスター / スレーブ
MasterSlave
Slave
Slave
1:N
Master+ Slave
Master+ Slave
マルチマスター
Master+ Slave
Master+ Slave
Master+ Slave
循環型
Master Slave
カスケード
Slave
MySQL 5.5 のおさらい準同期レプリケーション
マスター スレーブ
ストレージエンジン
ストレージエンジン
バイナリログ リレーログ
接続スレッド
アプリケーション
スレーブ接続スレッド
I/Oスレッド
SQLスレッド
1. COMMIT
2. バイナ
リログ
更新3. テーブル
更新
7. send_ok
4. バイナリログ送信
5. リレーログ更新
6-2. 更新の適用
6-1-1. ack6-1-2. ack
COMMIT完了時にはスレーブへ更新が到達しているることが保証されている。
→ HA (高可用性)として利用可能か!?
準同期レプリケーションによるHA
● できるようになったこと– マスタークラッシュ時に
スレーブにデータが残る
– 1:1構成
● できなかったこと– スレーブの昇格
● 1:N構成– スレーブのクラッシュへ
の対応● クラッシュ時は再
セットアップ
Global Transaction ID
● トランザクションを一意に識別することができる ID– UUID: トランザクション ID の形式で表現される– 例) 095E0FF8-18AF-11E2-9E7C-5C260A2AA986:123456
● トランザクション ID はシーケンス– 1:N環境で、どのスレーブが最も進んでいるか一目瞭然!
● MASTER_AUTO_POSITION = 1
Global Transaction ID (つづき)
mysql> show binlog events in 'mysql-bin.000002'\G
〜 省略 〜
*************************** 3. row *************************** Log_name: mysql-bin.000002 Pos: 151 Event_type: Gtid Server_id: 1End_log_pos: 199 Info: SET @@SESSION.GTID_NEXT= '095E0FF8-18AF-11E2-9E7C-5C260A2AA986:1'
〜 省略 〜
Global Transaction ID (つづき)mysql> SHOW SLAVE STATUS\G*************************** 1. row *************************** 〜 略 〜 Master_UUID: 095e0ff8-18af-11e2-9e7c-5c260a2aa986 Master_Info_File: /path/to/datadir/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 095E0FF8-18AF-11E2-9E7C-5C260A2AA986:1 Executed_Gtid_Set: 095E0FF8-18AF-11E2-9E7C-5C260A2AA986:11 row in set (0.00 sec)
マスター昇格時の操作 - ビフォー
SHOW BINLOG EVENTS等でそれぞれのサーバーのバイナリログの内容を比較するなどによって昇格するサーバーの対応するバイナリログポジションを調べて・・・
mysql> change master to master_host='127.0.0.1', -> master_port=13032, -> master_user = 'rsandbox', -> master_password = 'rsandbox', -> master_log_file = 'mysql-bin.123456', -> master_log_pos = 123456;Query OK, 0 rows affected (0.00 sec)
mysql> start slave;Query OK, 0 rows affected (0.00 sec)
マスター昇格時の操作 - アフター
mysql> change master to master_host='127.0.0.1', -> master_port=13032, -> master_auto_position = 1;Query OK, 0 rows affected (0.03 sec)
mysql> start slave user='rsandbox' password='rsandbox';Query OK, 0 rows affected, 1 warning (0.00 sec)
mysqlfailover
● マスターの自動的なフェイルオーバーを実行するツール● MySQL Workbench に付属
– MySQL Utilities の一部● 他にも便利なツールが!!
– Python製
mysqlfailover サンプルshell> mysqlfailover --master=root:[email protected]:13032 \ --slaves=root:[email protected]:13033,root:[email protected]:13034
MySQL Replication Failover UtilityFailover Mode = auto Next Interval = Thu Oct 18 22:42:14 2012
Master Information------------------Binary Log File Position Binlog_Do_DB Binlog_Ignore_DB mysql-bin.000006 191
Replication Health Status+------------+--------+---------+--------+------------+---------+| host | port | role | state | gtid_mode | health |+------------+--------+---------+--------+------------+---------+| 127.0.0.1 | 13032 | MASTER | UP | ON | OK || 127.0.0.1 | 13033 | SLAVE | UP | ON | OK || 127.0.0.1 | 13034 | SLAVE | UP | ON | OK |+------------+--------+---------+--------+------------+---------+
Q-quit R-refresh H-health G-GTID Lists U-UUIDs
mysqlfailover フェイルオーバーMySQL Replication Failover UtilityFailover Mode = auto Next Interval = Thu Oct 18 22:43:31 2012
Master Information------------------Binary Log File Position Binlog_Do_DB Binlog_Ignore_DB mysql-bin.000003 621
Replication Health Status+------------+--------+---------+--------+------------+---------+| host | port | role | state | gtid_mode | health |+------------+--------+---------+--------+------------+---------+| 127.0.0.1 | 13033 | MASTER | UP | ON | OK || 127.0.0.1 | 13034 | SLAVE | UP | ON | OK |+------------+--------+---------+--------+------------+---------+
Q-quit R-refresh H-health G-GTID Lists U-UUIDs
クラッシュセーフなスレーブ
● 以前のバージョン ● MySQL 5.6
InnoDB
レプリケーション情報=
relay_log_info ファイル
クラッシュセーフ
InnoDB の更新とは非同期
InnoDB
レプリケーション情報=
mysql.slave_relay_log_infoテーブル
フェイルオーバーのためのスレーブ用オプション
server_id=1log_bin=mysql-bin
gtid_mode=onlog_slave_updatesdisable_gtid_unsafe_statementsmaster_info_repository=TABLErelay_log_info_repository=TABLEreport_host=hostnamereport_port=3306
InnoDB
オンライン DDL
● MySQL 5.1ビルトインまで– 新しい定義のテーブルを作成してすべてのデータをコピー– ALTER TABLE中はテーブルの参照のみ可能– 更新は ALTER が終わるまでブロックされる
● MySQL 5.1 InnoDB Plugin〜 5.5– セカンダリインデックス追加時はデータのコピーをせずイン
デックスだけを構築– インデックス構築中は参照のみ可能
● MySQL 5.6– インデックス構築中の更新が可能に! New– 特殊なオプション等は特に必要なし
テーブルスペースのエクスポート / インポート
● テーブルを .ibd ファイルのコピーで他のマシンへ移行可能– innodb_file_per_table– MySQL 5.5 まではよくある間違いで、その操作はできなかった。
● MySQL 5.6 で実施可能に!– FLUSH TABLES t FOR EXPORT
テーブルスペースのエクスポート / インポート手順
● 移行元– FLUSH TABLES t FOR EXPORT;– .ibd ファイルと .cfg ファイルをコピー– UNLOCK TABLES;
● 移行先– テーブルの入れ物を作っておく
● CREATE TABLE t (…) ENGINE INNODB;● ALTER TABLE t DISCARD TABLESPACE;
– .ibd ファイルと .cfg ファイルをデータベースディレクトリ内にコピー
– ALTER TABLE t IMPORT TABLESPACE;
デッドロック検出機能
● 検出ロジックが高速に● エラーログに情報を出力
– innodb_print_all_deadlocks
デッドロックのログサンプルInnoDB: transactions deadlock detected, dumping detailed information.121018 2:28:28*** (1) TRANSACTION:TRANSACTION 6426, ACTIVE 16 sec starting index readmysql tables in use 1, locked 1LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s), undo log entries 1MySQL thread id 1, OS thread handle 0x7f126453c700, query id 53 localhost msandbox updatingupdate t set b='sss' where a=1*** (1) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 6 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` trx id 6426 lock_mode X locks rec but not gap waitingRecord lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 0: len 4; hex 00000001; asc ;; 1: len 6; hex 000000001917; asc ;; 2: len 7; hex 13000001890110; asc ;; 3: len 3; hex 747474; asc ttt;;
*** (2) TRANSACTION:TRANSACTION 6423, ACTIVE 65 sec starting index read
〜 略 〜
*** WE ROLL BACK TRANSACTION (2)
CPU スケーラビリティの向上
● MySQL Connect のキーノートスピーチで言及された数値– R/W sysbench … MySQL 5.5比で 151%改善!– Read Only sysbench … MySQL 5.5比で 234%改善!– http://medianetwork.oracle.com/video/player/1873154739001
● kernel_mutex における処理の分散● リードオンリートランザクション
– 更新の準備が不要なためオーバーヘッドが小さい● START TRANACTION READ ONLY● autocommit=1 における SELECT
フラッシュのアルゴリズム改善
● Adaptive Flushing の細かなチューニング– リソースが不足しそうになるとよりアグレッシブなフラッシュ
を開始する low water mark を指定可能に● innodb_adaptive_flushing_lwm● innodb_max_dirty_pages_pct_lwm
– リソースが逼迫した時の I/O の量を指定可能に● innodb_io_capacity_max
– フラッシュ動作変更の間隔を指定可能● innodb_flushing_avg_loops
● フラッシュ専用のバックグラウンドスレッド pager_cleaner– 毎秒起動– innodb_lru_scan_depth でスレッドが検査するサイズを
指定可能● ストレージに合わせたフラッシュ動作
– innodb_flush_neighbors
memcached プラグイン
MySQL サーバー
InnoDB
SQLパーサオプティマイザ等
接続
スレ
ッド
接続
スレ
ッド
memcachedプラグイン
接続
スレ
ッド
MySQLクライアント
MySQLクライアント
MySQLクライアント
memcachedクライアント
memcachedクライアント
ポート 3306 ポート 11211
オプティマイザ
〜 MySQL 5.5Nested Loop Join
SELECT … FROM t1 JOIN t2 ON … WHERE ...
for each row in t1 matching where condition { for each row in t2 matching join and where condition { send joined row to client }}
〜 MySQL 5.5Block Nested Loop Join
JOIN Buffer
t1 t2
1. WHERE句の条件に沿ってt1からレコードをフェッチしバッファに格納
2. バッファが満タンになったら t2 をスキャンして JOIN
3. t1 のすべてのレコードについてくりかえし
スキャン
Using Join Buffer...
MySQL 5.6 におけるオプティマイザ改善点
● Disk Sweep Multi Range Read (MRR)● Batched Key Access Join (BKA)● Index Condition Pushdown (ICP)● ORDER BY … LIMIT の効率化● サブクエリのアルゴリズム改善
– Semi-Join– FROM句のサブクエリの改善
MRR がない場合
セカンダリインデックス レコード
レコードにランダムアクセス
MRR がある場合
セカンダリインデックス レコード
MRR
レコードの ROWID をバッファに格納し、ROWID でソート。
ROWID順でアクセス。
Batched Key Access Join
JOIN Buffer
t1 t2
1. WHERE句の条件に沿ってt1からレコードをフェッチしバッファに格納
2. バッファが満タンになったら MRR で t2からレコードをフェッチしてJOIN
4. t1 のすべてのレコードについてくりかえし
MRRScan
3. ROWID の順でt2からレコードをフェッチ
Index Condition Pushdown
● 複合インデックスを用いたアクセスの効率化● (col1, col2, col3) というインデックスがある場合、これまで
は WHERE col1=1 AND col3<10 というような条件ではcol3はテーブルからレコードをフェッチする際に評価されなかった。
ICP がない場合セカンダリインデックス レコードcol1 col2 col3
0 20 10
1 3 4
1 3 10
1 3 20
1 8 2
1 9 9
:
1 9 11
1 9 15
1 11 5
1 11 13
:
2 1 2
col1=1 のすべてのレコードをフェッチ。col3の条件は使われない。
ICP がある場合セカンダリインデックス レコード
col1 col2 col3
0 20 10
1 3 4
1 3 10
1 3 20
1 8 2
1 9 9
:
1 9 11
1 9 15
1 11 5
1 11 13
:
2 1 2
フェッチされずに済んだレコード
col1=1かつ col3<10の条件に合うレコードだけをフェッチ。
ORDER BY … LIMIT の効率化
● SELECT column_list FROM single_table ORDER BY non_indexed_colum LIMIT n
– というような構造のクエリが速くなる。– Using sort buffer...
● 従来のアルゴリズム– すべての結果をソートしてから上位の n個を返す
● MySQL 5.6 のアルゴリズム– ソートバッファに n個のレコードが確実に格納出来るとわかっている場合、上位の結果だけをソートバッファに格納する
– ソートバッファに収まらない場合は従来のアルゴリズム
Semi Join
● 相関サブクエリの効率を改善– 従来のアルゴリズム=外部クエリから1行フェッチするごと
に、サブクエリを実行– 相関のないサブクエリは最初に1度だけ実行されるので遅
くはない● 従来は開発者が JOIN に書き換える必要があった。
– 多くの場合は SELECT DISTINCT で対応可能● Semi Join とは、重複を含まないサブクエリのこと。外部ク
エリ1行に対して最大で1行だけマッチする Join のこと。– SQL には Semi Join に該当する Join はない。
MySQL 5.5 の例 - EXPLAINEXPLAIN SELECT COUNT(1) FROM Country WHERE Country.Code IN (SELECT City.CountryCode FROM City WHERE Name LIKE 'A%')\G*************************** 1. row *************************** id: 1 select_type: PRIMARY table: Country type: indexpossible_keys: NULL key: PRIMARY key_len: 3 ref: NULL rows: 247 Extra: Using where; Using index*************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: City type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4037 Extra: Using where2 rows in set (0.00 sec)
MySQL 5.5 の例 - SELECT
mysql> SELECT COUNT(1) FROM Country WHERE Country.Code IN (SELECT City.CountryCode FROM City WHERE Name LIKE 'A%')\G*************************** 1. row ***************************COUNT(1): 711 row in set (0.26 sec)
mysql> SHOW STATUS LIKE 'handler_read%';+-----------------------+--------+| Variable_name | Value |+-----------------------+--------+| Handler_read_first | 240 || Handler_read_key | 240 || Handler_read_last | 0 || Handler_read_next | 239 || Handler_read_prev | 0 || Handler_read_rnd | 0 || Handler_read_rnd_next | 824291 |+-----------------------+--------+7 rows in set (0.00 sec)
MySQL 5.6 の例 - EXPLAINEXPLAIN SELECT COUNT(1) FROM Country WHERE Country.Code IN (SELECT City.CountryCode FROM City WHERE Name LIKE 'A%')\G*************************** 1. row *************************** id: 1 select_type: SIMPLE table: Country type: indexpossible_keys: PRIMARY key: PRIMARY key_len: 3 ref: NULL rows: 239 Extra: Using where; Using index*************************** 2. row *************************** id: 1 select_type: SIMPLE table: <subquery2> type: eq_refpossible_keys: <auto_key> key: <auto_key> key_len: 3 ref: world.Country.Code rows: 1 Extra: NULL ・・・つづく
MySQL 5.6 の例 - EXPLAINつづき
*************************** 3. row *************************** id: 2 select_type: MATERIALIZED table: City type: ALLpossible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 4188 Extra: Using where3 rows in set (0.00 sec)
MySQL 5.6 の例 - SELECT
mysql> SELECT COUNT(1) FROM Country WHERE Country.Code IN (SELECT City.CountryCode FROM City WHERE Name LIKE 'A%')\G*************************** 1. row ***************************COUNT(1): 711 row in set (0.00 sec)
mysql> SHOW STATUS LIKE 'handler_read%';+-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| Handler_read_first | 2 || Handler_read_key | 241 || Handler_read_last | 0 || Handler_read_next | 239 || Handler_read_prev | 0 || Handler_read_rnd | 0 || Handler_read_rnd_next | 4080 |+-----------------------+-------+7 rows in set (0.00 sec)
FROM 句のサブクエリ
● 評価の遅延– マテリアライゼーションが実際にレコードが必要な場合だけ
行われるように。– EXPLAIN が高速化。– WHERE句の条件次第ではマテリアライゼーションが不要
に。● マテリアライゼーションによって作成されたテンポラリテー
ブルにインデックスを作成。
MySQL 5.5 の例
mysql> SELECT COUNT(1) FROM Country C1 JOIN (SELECT * FROM City) AS C2 ON (C1.Capital = C2.ID) WHERE C1.Name LIKE 'X%';+----------+| COUNT(1) |+----------+| 0 |+----------+1 row in set (0.00 sec)
mysql> SHOW STATUS LIKE 'handler_read%';+-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| Handler_read_first | 2 || Handler_read_key | 2 || Handler_read_last | 0 || Handler_read_next | 0 || Handler_read_prev | 0 || Handler_read_rnd | 0 || Handler_read_rnd_next | 4320 |+-----------------------+-------+7 rows in set (0.00 sec)
MySQL 5.6 の例
mysql> SELECT COUNT(1) FROM Country C1 JOIN (SELECT * FROM City) AS C2 ON (C1.Capital = C2.ID) WHERE C1.Name LIKE 'X%';+----------+| COUNT(1) |+----------+| 0 |+----------+1 row in set (0.00 sec)
mysql> SHOW STATUS LIKE 'handler_read%';+-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| Handler_read_first | 1 || Handler_read_key | 1 || Handler_read_last | 0 || Handler_read_next | 0 || Handler_read_prev | 0 || Handler_read_rnd | 0 || Handler_read_rnd_next | 240 |+-----------------------+-------+7 rows in set (0.00 sec)
まとめ
● MySQL 5.6 には大幅な新機能が追加された。– 本日紹介したもの
● レプリケーション● InnoDB● オプティマイザ
● MySQL は急速に進化中!!● GA (正式版)リリースをお楽しみに。
ご静聴ありがとうございました。