多くの人にとって、MySQL Achillesのかかとは暗黙のコミットです。
本の 418ページのパラグラフ3によると
次のコマンドは、トランザクションを中断する可能性があります。
ALTER TABLE
BEGIN
CREATE INDEX
DROP DATABASE
DROP INDEX
DROP TABLE
RENAME TABLE
TRUNCATE TABLE
LOCK TABLES
UNLOCK TABLES
SET AUTOCOMMIT = 1
START TRANSACTION
提案
MySQLの場合、構築するContinuousIntegration(CI)/ SelfServiceジョブは、常にトランザクションジョブとDDLスクリプトを相互に排他的にする必要があります。
これにより、次のようなパラダイムを作成できます。
START TRANSACTION/COMMIT
ブロックで適切に分離されたトランザクションをサポートする
- DDLを自分でスクリプト化し、そのようなDDLをコンストラクターまたはデストラクターとして実行することによるDDLの制御
- コンストラクター:新しいデザインのテーブルを作成するDDL
- デストラクタ:テーブルを以前のデザインに戻すDDL
- これらの操作を1つのジョブにまとめないでください
警告:これにMyISAMを使用している場合、おそらく暗黙的なコミットの観点ではなく、データの一貫性の観点から、トランザクションを中断する可能性のあるもののリストにMyISAMを追加することができます。必要です。
なぜLVMではないのですか?
LVMスナップショットは優れており、重いSQL処理を実行せずにデータベースのインスタンス全体を復元することが理想的です。ただし、MySQLに関しては、InnoDBとMyISAMの2つのストレージエンジンを考慮する必要があります。
All-InnoDBデータベース
InnoDBのアーキテクチャを見てください(写真はPercona CTOのVadim Tkachenkoの好意による)
InnoDBには多くの可動部分があります
- システム表領域
- データ辞書
- ダブルライトバッファ(データの一貫性をサポート。クラッシュリカバリに使用)
- バッファーの挿入(セカンダリーの非一意索引へのバッファーの変更)
- ロールバックセグメント
- スペースを元に戻す(最も制御できない成長が発生する可能性のある場所)
- InnoDBバッファープール
- ダーティデータページ
- 汚れたインデックスページ
- 非ユニークインデックスの変更
- その他の重要なメモリキャッシュ
コミットされていない変更がバッファプールとメモリキャッシュに浮かんでいるすべてのInnoDBデータベースのLVMスナップショットを取得すると、LUNが復元されmysqldが起動するとInnoDBクラッシュリカバリが必要なデータセットが生成されます。
ALL-InnoDBの提案
スナップショットを撮る前にMySQLをシャットダウンできる場合
- 走る
SET GLOBAL innodb_fast_shutdown = 0;
- 走る
SET GLOBAL innodb_max_dirty_pages_pct = 0;
- 走る
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
- Innodb_buffer_pool_pages_dirtyが0または可能な限り0に近づくまで、手順3を繰り返します。
service mysql stop
- LVMスナップショットを撮る
service mysql stop
シャットダウンできないがMySQL Liveでスナップショットを撮る場合
- 走る
SET GLOBAL innodb_max_dirty_pages_pct = 0;
- 走る
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
- Innodb_buffer_pool_pages_dirtyが0または可能な限り0に近づくまで、手順2を繰り返します。
- LVMスナップショットを撮る
- 走る
SET GLOBAL innodb_max_dirty_pages_pct = 75;
All-MyISAMデータベースまたはInnoDB / MyISAM Mix
MyISAMは、アクセスされると、それに対する開いているファイルハンドルの数を維持します。MySQLがクラッシュすると、開いているファイルハンドルカウントが0を超えるMyISAMテーブルは、クラッシュとしてマークされ、修復が必要です(データに問題がない場合でも)。
使用中のMyISAMテーブルがあるデータベースのLVMスナップショットを取得すると、スナップショットが復元されmysqldが開始されたときに修復が必要な1つ以上のMyISAMテーブルがあります。
All-MyISAMまたはInnoDB / MyISAM Mixの提案
スナップショットを撮る前にMySQLをシャットダウンできる場合
- 走る
SET GLOBAL innodb_fast_shutdown = 0;
- 走る
SET GLOBAL innodb_max_dirty_pages_pct = 0;
- 走る
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
- Innodb_buffer_pool_pages_dirtyが0または可能な限り0に近づくまで、手順3を繰り返します。
service mysql stop
- LVMスナップショットを撮る
service mysql stop
シャットダウンできないがMySQL Liveでスナップショットを撮る場合
特定のInnoDBテーブルのフラッシュを強制できます
- 走る
SET GLOBAL innodb_max_dirty_pages_pct = 0;
- 走る
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';
- Innodb_buffer_pool_pages_dirtyが0または可能な限り0に近づくまで、手順2を繰り返します。
FLUSH TABLES innodb_tbl1,... FOR EXPORT;
重要なInnoDBテーブルで実行する
- 走る
FLUSH TABLES WITH READ LOCK;
- LVMスナップショットを撮る
- 走る
UNLOCK TABLES;
- 走る
SET GLOBAL innodb_max_dirty_pages_pct = 75;
MySQL Replicationは役立ちますか?
1つのLVMスナップショットを2つのサーバーに復元し、MySQL Master / Slave Replicationをセットアップすることもできますが、スナップショットを復元する際のハウスクリーニングの追加ソースになります。
CIジョブをマスターで実行し、それらのジョブが小さい場合、特定の状況下で複製が時間の節約になる可能性があります。STOP SLAVE;
スレーブで実行し、マスターでCIジョブを開始しSTART SLAVE;
、マスターのデータが認証されたらスレーブで実行できます。
CIジョブが大量のデータを警告する場合、LVMスナップショットを復元し、レプリケーションをゼロからセットアップできます。頻繁にこれを行うことに気付いた場合は、おそらくMySQLレプリケーションのセットアップを行うことができます。
最終的な考え
- 複数のDBサーバー(3つ以上)を使用して、復元と回帰テストを実行することをお勧めします。
- テーブルがMyISAMのままである必要がない場合、残りのMyISAMテーブルをInnoDBに変換します。
- データコンテンツが機密である場合は、テストを開始する前にスナップショットを復元した後、CIジョブを実行してデータをスクラブする必要があります。別の方法として、データを既にスクラブしたMySQLのスナップショットを作成することもできます。