web-dev-qa-db-ja.com

ライブMyISAMテーブルをInnoDBに変換する

Webトラフィックを追跡するテーブルがあります。テーブルは常に書き込まれ、読み取られます。テーブルのサイズがかなり大きいので、テーブルのストレージエンジンをMyISAM-> InnoDBから変換するプロセスでアプリケーションが「フリーズ」しないようにする必要があります。以下は、他の投稿から収集した情報に基づいて、私が計画していることです。不足しているものがあれば教えてください。

  1. mysqldump -u -p --lock-tables=false mydb tracking > tracking.sql-私が理解していることから、これは「追跡」テーブルをロックするべきではありません
  2. SQLファイルのテーブル名をtracking_newに変更します
  3. mysql -u -p mydb < tracking.sql
  4. ALTER TABLE mydb.tracking_new ENGINE=InnoDB;
  5. ダンプの実行中に元のテーブルに書き込まれた「tracking_new」テーブルに新しい行を挿入します

    SELECT @last_id := tracking.id FROM mydb.tracking_new ORDER BY tracking.id DESC LIMIT 1;    
    INSERT INTO mydb.tracking_new
    SELECT * FROM mydb.tracking WHERE tracking.id > @last_id;
    

テーブルの名前を変更する

RENAME TABLE 
    mydb.tracking TO mydb.tracking_old, 
    mydb.tracking_new TO mydb.tracking;
2
marcin_koss

そのテーブルにトリガーがないと仮定すると、テーブルをロックせずにこれを行う最も簡単な方法は pt-online-schema-change

この変更に対応するのに十分な追加のディスク容量があることを確認してください。テーブルをInnoDBに変換するとサイズが大きくなり、変換中にテーブルの両方のコピーを維持する必要があります。たとえば、テーブルが100 GBの場合、少なくとも200 GB以上の空きディスク容量があることを確認してください。

最初に非運用環境でこれをテストして、それが機能することを確認し、必要なディスク容量を正確に調べる必要があります。

ケースの構文は非常に単純です。

最初に予行演習を行い、機能することを確認します。

pt-online-schema-change --alter "ENGINE=InnoDB" D=mydb,t=tracking --dry-run

次にそれを実行します:

pt-online-schema-change --alter "ENGINE=InnoDB" D=mydb,t=tracking --execute
3
Ike Walker

MyISAMテーブルをロードして後で変更する代わりに、SQLダンプファイル(テーブル定義上)でMySQLエンジンを直接変更します。

テーブルはInnoDB engineに直接復元されます:

MyISAM

CREATE TABLE `test` (
  `t` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1

InnoDB

CREATE TABLE `test` (
  `t` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1

ステップ5は良いようです。

ベスト、

マックス。

0

追跡テーブルがMyISAMの場合、おそらく concurrent_insert に依存する必要があります。これにより、MyISAMテーブルの中央にある穴をロックせずに、追跡テーブルに新しい行を追加できます。入ってくるすべての行をすばやく簡単に追加するだけです。

concurrent_insert を2に設定すると、トラッキングテーブルに書き込み、データをコピーできるようになります。

ここに別の提案があります:

STEP 01:常に追加するには、concurrent_sizeをアクティブにします

mysql -Dmydb -ANe"SET GLOBAL concurrent_insert = 2"

STEP 02:テーブルのInnoDBバージョンを作成します

SQL="CREATE TABLE tracking_innodb LIKE tracking;"
SQL="${SQL} ALTER TABLE tracking_innodb ENGINE=InnoDB;"
mysql -Dmydb -ANe"${SQL}"

STEP 03:トラッキングテーブルのコピーを新しいテーブルに直接実行します

mysqldump --no-create-info mydb tracking | sed 's/tracking/tracking_innodb' | mysql -Dmydb

STEP 04:新しい挿入を防ぐためにトラッキングテーブルの名前を変更します

mysql -Dmydb -ANe"ALTER TABLE tracking RENAME tracking_old"

STEP 05:tracking_oldで最後のIDを取得します

SQL="SELECT id FROM tracking_new ORDER BY tracking.id DESC LIMIT 1"
LASTID=`mysql -Dmydb -ANe"`

STEP 06:残りのデータを取得します

SQL="INSERT INTO tracking_new SELECT * FROM tracking_odl WHERE id > ${LASTID}"
mysql -Dmydb -ANe"${SQL}"

STEP 07:tracking_newの名前をtrackingに変更します

mysql -Dmydb -ANe"ALTER TABLE tracking_new RENAME tracking"

警告

あなたの元の提案は実際には同じくらい良いです。とにかく私の答えのほとんどはあなたのように見えます。唯一の違いは、STEP 04で始まる新しい挿入がないことを保証するために停止を導入することです。計画の少し早い段階で停止が発生します(STEP 02)。

Mysqldumpの実行中にMyISAMテーブルへの挿入を高速化するために、concurrent_insertを追加しました。

あなたはあなたの計画か私のどちらかで行くことができます。ミックスにconcurrent_insert=2を追加するだけです。

試してみる !!!

0
RolandoMySQLDBA