常に更新があるテーブルの MySQL テーブル文字コードの変更
本番運用中のMySQLのデフォルト文字コードが以前と変わってしまってることが発覚して
その間に作られたテーブルの文字コードを修正したいです
ほとんどのテーブルは修正できたのですが
ユニークカラム user_id をもっていて頻繁に更新されるテーブルに
ALTER TABLE user_states DEFAULT CHARACTER SET utf8
実行しようとしたところ
Error Code: 1062. Duplicate entry
xxxxxxxx` for key 'index_user_states_on_user_id'
というエラーが出てしまいます
当然ユニーク制約がついてるためレコードは1つしかないです
文字コード変更中に書き込みされて文字列の比較がうまくいかなくて
変なことが起こってるのかなと推測していますが
どうにか更新を行う方法はないでしょうか
要件としては
このテーブル自体は多少(数秒程度なら)欠損がでても問題ないですが
書き込んでる API 側や MySQL 全体を停止したりネットワークから切り離すのはNGです
SQLで明示的にテーブル単位でロックがとれれば
LOCK;
ALTER TABLE user_states DEFAULT CHARACTER SET utf8;
UNLOCK;
みたいな感じで数秒だけ書き込みを抑制して文字コード変更が完了できると思うんですが…
そういうことってできないでしょうか
追記:
Rails のマイグレーションエラー全文
execute("ALTER TABLE user_states DEFAULT CHARACTER SET utf8")
rake stderr: rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Duplicate entry 'xxxxxxxxxxxxxxxxxxx' for key 'index_user_states_on_user_id': ALTER TABLE user_states DEFAULT CHARACTER SET utf8
xxxxxxxxxxxxxxx
は実行するたびに変わっていてそのユーザのデータが直前に更新されているので
文字コード変更とINSERTが重なっておかしなことになってると推測しました
もちろんユニーク制約があるので重複データは存在しません
INSERT INTO user_states (user_id, state) VALUES(xxxxxx, xxx)
ON DUPLICATEKEY UPDATE state = state
同時に大量に飛んでくる更新クエリはこんな感じです