Bug(バグ) #2439
1.4.0 で追加されたマイグレートスクリプト (リビジョン番号 9) の実行に失敗することがある
100%
Description
DB に存在するデータの状態によっては、 #2346 の対応のために追加された 009_change_cascade_diary_comment.php の実行に失敗することがある。
失敗時のエラーメッセージは以下のようになる。
Error #1 - SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`DBNAME`.<result 2 when explaining filename '#sql-393e_3577b6'>, CONSTRAINT `diary_comment_member_id_member_id` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`) ON DELETE SET NULL). Failing Query: "ALTER TABLE `diary_comment` ADD CONSTRAINT diary_comment_member_id_member_id FOREIGN KEY (member_id) REFERENCES `member`(id) ON DELETE SET NULL"
このようなエラーが生じる原因として、 diary_comment.member_id カラムに存在しないメンバー ID (たとえば、既に退会してしまったメンバー) が含まれている可能性が考えられる。
- OpenPNE 2 では、 #2346 で説明しているように、メンバー退会時に日記コメントに紐付くメンバー ID が空になる (NULL に置き換わる)
- OpenPNE 3 では、 #2346 の修正前ではメンバー退会時に日記コメントが削除されていた。 #2346 の修正後は OpenPNE 2 と同じ挙動になった
- ただし、 OpenPNE 2 は OpenPNE 3 と違い外部キー制約を使用していないため、退会者の日記コメントのうち、メンバー ID が空になっていないレコードが存在する可能性を否定できない。 OpenPNE 2 から OpenPNE 3 へのアップグレードは外部キー制約を一時的に無効にしておこなうため、 diary_comment_member_id_member_id の制約に違反するレコードは OpenPNE 3 に存在しうる
Related issues
Associated revisions
(fixes #2439) fixed not to fail migrate when the member ids dropped exist in diary_comment table
(fixes #2439) fixed DQL to upper case
(fixes #2439) replace DQL to SQL
(refs #2439) fixed migrate script
History
#1 Updated by Kousuke Ebihara about 13 years ago
https://github.com/balibali/opDiaryPlugin/blob/master/data/migrations/1.3.0/008_add_foreign_key_on_diary_comment_unread.php のように制約違反になりそうなデータを事前に是正しておくのが対応としてはよさそうです
#2 Updated by Kousuke Ebihara about 13 years ago
- 360対象 changed from 3.6.0 to RC2
#3 Updated by Yuya Watanabe about 13 years ago
- Status changed from New(新規) to Accepted(着手)
- Assignee set to Yuya Watanabe
#4 Updated by Yuya Watanabe about 13 years ago
確認方法¶
- 事前準備
- サーバでopenpne3.6RC1をインストールの状態にする
- ブラウザで以下を実行する
- メンバを二人作成する(メンバAとメンバBとする)
- メンバAで日記Aを書く
- メンバBで日記Aに対しコメントを書く
- 環境作成
- サーバ上のmysqlで以下を実行する
- use データベース名;
- alter table diary_comment drop foreign key diary_comment_diary_id_diary_id;
- update sns_config set value=8 where name='opDiaryPlugin_revision';
- ブラウザで以下を実行する
- メンバBで退会する
- 確認
- ./symfony openpne:migrate --target=opDiaryPlugin
- 2つエラーが発生し,2つ目が本チケットに記載されているエラーとなっている
- 1つ目のエラーは外部キー制約が存在しない場合に発生するエラー
#5 Updated by Yuya Watanabe about 13 years ago
修正方針¶
note-1のように,memberテーブルに存在しないmember_idを持つdiary_commentテーブルのレコードについて,member_idにNULLに変更する処理を追加します.
実装案¶
diff --git a/data/migrations/1.3.3/009_change_cascade_diary_comment.php b/data/migrations/1.3.3/009_change_cascade_diary_comment.php index 7624dd1..f0d8728 100644 --- a/data/migrations/1.3.3/009_change_cascade_diary_comment.php +++ b/data/migrations/1.3.3/009_change_cascade_diary_comment.php @@ -18,6 +18,22 @@ */ class opDiaryPluginMigrationVersion9 extends opMigration { + public function preUp() + { + Doctrine::getTable('DiaryComment')->createQuery()->update() + ->set('DiaryComment.member_id', 'NULL') + ->where('DiaryComment.member_id NOT IN (select member.id from member)') + ->execute(); + } + + public function preDown() + { + Doctrine::getTable('DiaryComment')->createQuery()->update() + ->set('DiaryComment.member_id', 'NULL') + ->where('DiaryComment.member_id NOT IN (SELECT member.id FROM member)') + ->execute(); + } + public function up() { $option = array(
#6 Updated by Yuya Watanabe about 13 years ago
- Status changed from Accepted(着手) to Pending Review(レビュー待ち)
- % Done changed from 0 to 50
#7 Updated by Mutsumi Imamura about 13 years ago
- Status changed from Pending Review(レビュー待ち) to Rejected(差し戻し)
このチケットの問題が発覚した際と同じデータでテストしてみたところ下記のエラーが出力されました。ご確認ください。
SQLSTATE[HY000]: General error: 1005 Can't create table './DB名/#sql-936_d572.frm' (errno: 121). Failing Query: "ALTER TABLE diary ADD CONSTRAINT diary_member_id_member_id FOREIGN KEY (member_id) REFERENCES member(id) ON DELETE CASCADE". Failing Query: ALTER TABLE diary ADD CONSTRAINT diary_member_id_member_id FOREIGN KEY (member_id) REFERENCES member(id) ON DELETE CASCADE
#8 Updated by Yuya Watanabe about 13 years ago
note-7のエラーについて¶
このエラーが発生する原因として考えられるものとして,チケットの記述と同様に外部キー制約が存在しない状態で退会したメンバの日記が削除されていないということが考えられます.この場合,存在しないmember_idが存在するのはdiaryテーブルであると思います.また,本チケットの問題発生原因がリビジョン9のマイグレートスクリプトであり,このスクリプトはdiary_commentのカスケードについて修正を行うという趣旨であると思います.そのため,リビジョン9のマイグレートスクリプト単体でのマイグレートで対処を行うことはこのスクリプトの意図と乖離する可能性があるため,別チケットで対応することが適切であると思いました.
#9 Updated by Yuya Watanabe about 13 years ago
- Status changed from Rejected(差し戻し) to Pending Review(レビュー待ち)
note-8に記述したとおりnote-7のエラーは本チケットで対応しないほうがいいと思ったのでステータスをレビュー待ちにします.
#10 Updated by Rimpei Ogawa about 13 years ago
- Target version changed from v1.4.1 to v1.4.0.1
#11 Updated by Kousuke Ebihara about 13 years ago
- Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
- % Done changed from 50 to 70
OK です。
http://redmine.openpne.jp/issues/2439#note-7 の問題についてはチケットを作成してください(軽く確認したところ、 diary_member_id_member_id の作成のための ALTER 文を実行するマイグレートスクリプトが見当たらず、いったいどのようにしてその現象を発生させたのかよくわかりませんでした)
#12 Updated by Mutsumi Imamura about 13 years ago
Kousuke Ebihara は書きました:
OK です。
http://redmine.openpne.jp/issues/2439#note-7 の問題についてはチケットを作成してください(軽く確認したところ、 diary_member_id_member_id の作成のための ALTER 文を実行するマイグレートスクリプトが見当たらず、いったいどのようにしてその現象を発生させたのかよくわかりませんでした)
#2448 でチケットが作成されています
#13 Updated by Mutsumi Imamura about 13 years ago
- Status changed from Pending Testing(テスト待ち) to Fixed(完了)
- % Done changed from 70 to 100
動作確認しました。問題ありません。
下記のようなメンバーかつ、日記コメントのデータの状態でmigrateを実行し正常に完了することを確認しました。
mysql> select * from member; +----+------------+------------------+-------------------+---------------------+---------------------+-----------+ | id | name | invite_member_id | is_login_rejected | created_at | updated_at | is_active | +----+------------+------------------+-------------------+---------------------+---------------------+-----------+ | 1 | OpenPNE君 | NULL | 0 | 2011-09-30 18:19:35 | 2011-09-30 18:21:47 | 1 | | 2 | imamura | 1 | 0 | 2011-09-30 18:23:16 | 2011-09-30 18:23:16 | 1 | +----+------------+------------------+-------------------+---------------------+---------------------+-----------+ 2 rows in set (0.00 sec)
mysql> select * from diary_comment; +----+----------+-----------+--------+------------+------------+---------------------+---------------------+ | id | diary_id | member_id | number | body | has_images | created_at | updated_at | +----+----------+-----------+--------+------------+------------+---------------------+---------------------+ | 1 | 10 | 0 | 1 | pppppppp | 0 | 2011-09-30 18:24:39 | 2011-09-30 18:24:39 | | 2 | 10 | 0 | 2 | pppppppp | 0 | 2011-09-30 18:24:42 | 2011-09-30 18:24:42 | | 3 | 10 | 0 | 3 | pppppppp | 0 | 2011-09-30 18:24:44 | 2011-09-30 18:24:44 | | 4 | 10 | 0 | 4 | pppppppp | 0 | 2011-09-30 18:24:47 | 2011-09-30 18:24:47 | | 5 | 5 | 1234 | 1 | ddddddddd | 0 | 2011-09-30 18:25:01 | 2011-09-30 18:25:01 | | 6 | 5 | 1234 | 2 | dddddddddd | 0 | 2011-09-30 18:25:06 | 2011-09-30 18:25:06 | | 7 | 5 | 1234 | 3 | dddddd | 0 | 2011-09-30 18:25:11 | 2011-09-30 18:25:11 | +----+----------+-----------+--------+------------+------------+---------------------+---------------------+ 7 rows in set (0.00 sec)
#14 Updated by Yuya Watanabe about 13 years ago
- Status changed from Fixed(完了) to Pending Review(レビュー待ち)
- % Done changed from 100 to 50
レビュー,テスト終了してましたが,DQLの予約語やモデルの先頭を小文字にしていたため,下記コミットを行いました.
https://github.com/balibali/opDiaryPlugin/commit/21c2b98305869e1a3e93bb5b5d46436670003aa7
#15 Updated by Kousuke Ebihara about 13 years ago
- Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
- % Done changed from 50 to 70
#16 Updated by Yuya Watanabe about 13 years ago
- Status changed from Pending Testing(テスト待ち) to Pending Review(レビュー待ち)
- % Done changed from 70 to 50
note-14の状態で動作しなかったためDQLをSQLに書き直しました.
https://github.com/balibali/opDiaryPlugin/commit/c8d26bbe7a32f1d314f946e99bb3166f2c8c7d8d
#17 Updated by Kousuke Ebihara about 13 years ago
- Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
- % Done changed from 50 to 70
#18 Updated by Yuya Watanabe about 13 years ago
- Status changed from Pending Testing(テスト待ち) to Pending Review(レビュー待ち)
- % Done changed from 70 to 50
#19 Updated by Kousuke Ebihara about 13 years ago
- Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
- % Done changed from 50 to 70
#20 Updated by Mutsumi Imamura about 13 years ago
再テストOKです。
#21 Updated by Mutsumi Imamura about 13 years ago
- Status changed from Pending Testing(テスト待ち) to Fixed(完了)
- % Done changed from 70 to 100