〜5M行のMySQLテーブルにインデックスを作成する必要があります。これは実稼働テーブルであり、CREATE INDEXステートメントを実行すると、すべてが完全にブロックされることを恐れます...
挿入と選択をブロックせずにそのインデックスを作成する方法はありますか?
停止して、インデックスを作成して、システムを再起動する必要はないのではないかと思っただけです!
https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html
MySQL 5.6以降では、インデックスが作成または削除されている間、テーブルは読み取りおよび書き込み操作で使用できます。 CREATE INDEXまたはDROP INDEXステートメントは、テーブルにアクセスしているすべてのトランザクションが完了した後にのみ終了するため、インデックスの初期状態はテーブルの最新の内容を反映します。以前は、インデックスの作成中または削除中にテーブルを変更すると、通常、テーブルのINSERT、UPDATE、またはDELETEステートメントがキャンセルされるデッドロックが発生しました。
上記の答えから:
"5.1インデックスを超えるバージョンを使用している場合は、データベースがオンライン中に作成されます。そのため、運用システムの使用を中断する心配はありません。"
これは**** FALSE ****です (少なくともMyISAM/InnoDBテーブルの場合、99.999%の人々が使用しています。ClusteredEditionは異なります。)
テーブルでUPDATE操作を行うと、インデックスの作成中に[〜#〜] block [〜#〜]が実行されます。 MySQLは、これ(および他のいくつかのこと)について本当に本当に愚かです。
テストスクリプト:
(
for n in {1..50}; do
#(time mysql -uroot -e 'select * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
(time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'
私のサーバー(InnoDB):
Server version: 5.5.25a Source distribution
出力(6番目の操作がインデックスの更新を完了するまでにかかる400msの間ブロックすることに注意してください):
1 real 0m0.009s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.012s
5 real 0m0.009s
Index Update - START
Index Update - FINISH
6 real 0m0.388s
7 real 0m0.009s
8 real 0m0.009s
9 real 0m0.009s
10 real 0m0.009s
11 real 0m0.009s
ブロックしない読み取り操作に対して(スクリプト内の行コメントを交換します):
1 real 0m0.010s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.010s
5 real 0m0.009s
Index Update - START
6 real 0m0.010s
7 real 0m0.010s
8 real 0m0.011s
9 real 0m0.010s
...
41 real 0m0.009s
42 real 0m0.010s
43 real 0m0.009s
Index Update - FINISH
44 real 0m0.012s
45 real 0m0.009s
46 real 0m0.009s
47 real 0m0.010s
48 real 0m0.009s
これまでのところ、MySqlスキーマを更新するために知っている方法は1つしかなく、可用性の停止を被ることはありません。円形マスター:
スキーマを更新する簡単な方法はそうではありません。深刻な実稼働環境で実行可能。はい、そうです。書き込みをブロックせずにMySQLテーブルにインデックスを追加する簡単な方法があれば、教えてください。
グーグルは、私に この記事 を導き、同様の手法を説明しています。さらに良いことに、彼らは手順の同じ時点で飲むことを勧めます(記事を読む前に私の答えを書いたことに注意してください)!
記事 上記でリンクしたツール pt-online-schema-change については、次のように機能します。
このツールを自分で試したことはありません。 YMMV
現在、 AmazonのRDS を使用してMySQLを使用しています。 MySQLをまとめて管理する非常に気の利いたサービスで、1つのボタンで新しいリードレプリカを追加し、ハードウェアSKU全体でデータベースを透過的にアップグレードできます。本当に便利です。データベースへのスーパーアクセスを取得できないため、レプリケーションを直接台無しにすることはできません(これは祝福ですか?)ただし、 Read Replica Promotion を使用して、読み取り専用スレーブでスキーマを変更し、そのスレーブを新しいマスターに昇格させることができます。上で説明したのとまったく同じトリックで、実行が非常に簡単です。彼らはまだあなたをカットオーバーで助けるために多くをしません。アプリを再構成して再起動する必要があります。
このように ブログ投稿 アウトライン、InnoDB ALTER TABLE
メカニズムはMySQL 5.6向けに完全に再設計されました。
(このトピックの排他的な概要については、 MySQLドキュメント を読んで午後の価値があります。)
インデックスをテーブルに追加するには、[ロックなしUPDATE
/INSERT
で結果を得るために、次のステートメント形式を使用できます。
ALTER TABLE my_table ADD INDEX my_table__idx (my_column), ALGORITHM=INPLACE, LOCK=NONE;
MySQL 5.6更新(2013年2月):InnoDBテーブルを使用してもインデックスの作成中に読み取りおよび書き込み操作を実行できるようになりました- http://dev.mysql.com/doc/refman/5.6/en/innodb -create-index-overview.html
MySQL 5.6以降では、インデックスが作成または削除されている間、テーブルは読み取りおよび書き込み操作で使用できます。 CREATE INDEXまたはDROP INDEXステートメントは、テーブルにアクセスしているすべてのトランザクションが完了した後にのみ終了するため、インデックスの初期状態はテーブルの最新の内容を反映します。以前は、インデックスの作成中または削除中にテーブルを変更すると、通常、テーブルのINSERT、UPDATE、またはDELETEステートメントがキャンセルされるデッドロックが発生しました。
そして:
MySQL 5.6では、この機能はより一般的になります。インデックスの作成中にテーブルの読み書きができ、テーブルをコピーせずに、DML操作をブロックせずに、またはその両方で、より多くの種類のALTER TABLE操作を実行できます。したがって、MySQL 5.6以降では、通常、この機能セットを高速インデックス作成ではなくオンラインDDLと呼びます。
from http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_fast_index_creation
pt-online-schema-changeは、移行によってサイトがダウンしないことを本当に確認したい場合の方法です。
上記のコメントで書いたように、プロダクションでのpt-online-schema-changeのいくつかの経験があります。 20M +レコードのメインテーブルと、マスター-> 2つの読み取り専用レプリケーションスレーブがあります。私は、pt-online-schema-changeを使用して、新しい列の追加、文字セットの変更、いくつかのインデックスの追加など、少なくとも数十回の移行を行いました。移行時にも大量のトラフィックを処理しますが、問題はありません。もちろん、運用環境で実行する前に、すべてのスクリプトを徹底的にテストする必要があります。
変更を1つのスクリプトにまとめて、pt-online-schema-changeがデータを1回コピーするだけで済むようにしました。また、データが失われるため、列名の変更には十分注意してください。ただし、インデックスを追加しても問題ありません。