Bug(バグ) #2439
完了1.4.0 で追加されたマイグレートスクリプト (リビジョン番号 9) の実行に失敗することがある
100%
説明
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 に存在しうる
Kousuke Ebihara さんが約13年前に更新
https://github.com/balibali/opDiaryPlugin/blob/master/data/migrations/1.3.0/008_add_foreign_key_on_diary_comment_unread.php のように制約違反になりそうなデータを事前に是正しておくのが対応としてはよさそうです
Yuya Watanabe さんが約13年前に更新
確認方法¶
- 事前準備
- サーバで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つ目のエラーは外部キー制約が存在しない場合に発生するエラー
Yuya Watanabe さんが約13年前に更新
修正方針¶
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(
Yuya Watanabe さんが約13年前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
Mutsumi Imamura さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から 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
Yuya Watanabe さんが約13年前に更新
note-7のエラーについて¶
このエラーが発生する原因として考えられるものとして,チケットの記述と同様に外部キー制約が存在しない状態で退会したメンバの日記が削除されていないということが考えられます.この場合,存在しないmember_idが存在するのはdiaryテーブルであると思います.また,本チケットの問題発生原因がリビジョン9のマイグレートスクリプトであり,このスクリプトはdiary_commentのカスケードについて修正を行うという趣旨であると思います.そのため,リビジョン9のマイグレートスクリプト単体でのマイグレートで対処を行うことはこのスクリプトの意図と乖離する可能性があるため,別チケットで対応することが適切であると思いました.
Yuya Watanabe さんが約13年前に更新
- ステータス を Rejected(差し戻し) から Pending Review(レビュー待ち) に変更
note-8に記述したとおりnote-7のエラーは本チケットで対応しないほうがいいと思ったのでステータスをレビュー待ちにします.
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
OK です。
http://redmine.openpne.jp/issues/2439#note-7 の問題についてはチケットを作成してください(軽く確認したところ、 diary_member_id_member_id の作成のための ALTER 文を実行するマイグレートスクリプトが見当たらず、いったいどのようにしてその現象を発生させたのかよくわかりませんでした)
Mutsumi Imamura さんが約13年前に更新
Kousuke Ebihara は書きました:
OK です。
http://redmine.openpne.jp/issues/2439#note-7 の問題についてはチケットを作成してください(軽く確認したところ、 diary_member_id_member_id の作成のための ALTER 文を実行するマイグレートスクリプトが見当たらず、いったいどのようにしてその現象を発生させたのかよくわかりませんでした)
#2448 でチケットが作成されています
Mutsumi Imamura さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 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)
Yuya Watanabe さんが約13年前に更新
- ステータス を Fixed(完了) から Pending Review(レビュー待ち) に変更
- 進捗率 を 100 から 50 に変更
レビュー,テスト終了してましたが,DQLの予約語やモデルの先頭を小文字にしていたため,下記コミットを行いました.
https://github.com/balibali/opDiaryPlugin/commit/21c2b98305869e1a3e93bb5b5d46436670003aa7
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Yuya Watanabe さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Pending Review(レビュー待ち) に変更
- 進捗率 を 70 から 50 に変更
note-14の状態で動作しなかったためDQLをSQLに書き直しました.
https://github.com/balibali/opDiaryPlugin/commit/c8d26bbe7a32f1d314f946e99bb3166f2c8c7d8d
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Yuya Watanabe さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Pending Review(レビュー待ち) に変更
- 進捗率 を 70 から 50 に変更
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Mutsumi Imamura さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更