プロジェクト

全般

プロフィール

Bug(バグ) #2439

1.4.0 で追加されたマイグレートスクリプト (リビジョン番号 9) の実行に失敗することがある

Kousuke Ebihara12年以上前に追加. 12年以上前に更新.

ステータス:
Fixed(完了)
優先度:
Normal(通常)
担当者:
対象バージョン:
開始日:
2011-09-26
期日:
進捗率:

100%

3.6 で発生するか:
[QA]バグ通知済:
いいえ
3.8 で発生するか:
Unknown (未調査)

説明

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 に存在しうる

関連するチケット

関連している opDiaryPlugin - Bug(バグ) #2448: 存在しないmemberが書いた日記が存在する場合にマイグレートに失敗する New(新規) 2011-09-29
関連している opDiaryPlugin - Bug(バグ) #2472: 1.4.0.1 で修正されたマイグレートスクリプト (リビジョン番号 9) の実行に失敗することがある Invalid(無効) 2011-10-06
関連している opDiaryPlugin - Bug(バグ) #2346: 退会時にそのメンバーが書いた日記コメントも削除されてしまう Fixed(完了) 2011-08-11

関係しているリビジョン

リビジョン 15afd6de (差分)
Yuya Watanabe12年以上前に追加

(fixes #2439) fixed not to fail migrate when the member ids dropped exist in diary_comment table

リビジョン 21c2b983 (差分)
Yuya Watanabe12年以上前に追加

(fixes #2439) fixed DQL to upper case

リビジョン c8d26bbe (差分)
Yuya Watanabe12年以上前に追加

(fixes #2439) replace DQL to SQL

リビジョン 4eabc986 (差分)
Yuya Watanabe12年以上前に追加

(refs #2439) fixed migrate script

履歴

#1 Kousuke Ebihara12年以上前に更新

https://github.com/balibali/opDiaryPlugin/blob/master/data/migrations/1.3.0/008_add_foreign_key_on_diary_comment_unread.php のように制約違反になりそうなデータを事前に是正しておくのが対応としてはよさそうです

#2 Kousuke Ebihara12年以上前に更新

  • 360対象3.6.0 から RC2 に変更

#3 Yuya Watanabe12年以上前に更新

  • ステータスNew(新規) から Accepted(着手) に変更
  • 担当者Yuya Watanabe にセット

#4 Yuya Watanabe12年以上前に更新

確認方法

  • 事前準備
    1. サーバでopenpne3.6RC1をインストールの状態にする
    2. ブラウザで以下を実行する
      1. メンバを二人作成する(メンバAとメンバBとする)
      2. メンバAで日記Aを書く
      3. メンバBで日記Aに対しコメントを書く
  • 環境作成
    1. サーバ上のmysqlで以下を実行する
      1. use データベース名;
      2. alter table diary_comment drop foreign key diary_comment_diary_id_diary_id;
      3. update sns_config set value=8 where name='opDiaryPlugin_revision';
    2. ブラウザで以下を実行する
      1. メンバBで退会する
  • 確認
    1. ./symfony openpne:migrate --target=opDiaryPlugin
      • 2つエラーが発生し,2つ目が本チケットに記載されているエラーとなっている
      • 1つ目のエラーは外部キー制約が存在しない場合に発生するエラー

#5 Yuya Watanabe12年以上前に更新

修正方針

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 Yuya Watanabe12年以上前に更新

  • ステータスAccepted(着手) から Pending Review(レビュー待ち) に変更
  • 進捗率0 から 50 に変更

#7 Mutsumi Imamura12年以上前に更新

  • ステータス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

#8 Yuya Watanabe12年以上前に更新

note-7のエラーについて

このエラーが発生する原因として考えられるものとして,チケットの記述と同様に外部キー制約が存在しない状態で退会したメンバの日記が削除されていないということが考えられます.この場合,存在しないmember_idが存在するのはdiaryテーブルであると思います.また,本チケットの問題発生原因がリビジョン9のマイグレートスクリプトであり,このスクリプトはdiary_commentのカスケードについて修正を行うという趣旨であると思います.そのため,リビジョン9のマイグレートスクリプト単体でのマイグレートで対処を行うことはこのスクリプトの意図と乖離する可能性があるため,別チケットで対応することが適切であると思いました.

#9 Yuya Watanabe12年以上前に更新

  • ステータスRejected(差し戻し) から Pending Review(レビュー待ち) に変更

note-8に記述したとおりnote-7のエラーは本チケットで対応しないほうがいいと思ったのでステータスをレビュー待ちにします.

#10 Rimpei Ogawa12年以上前に更新

  • 対象バージョンv1.4.1 から v1.4.0.1 に変更

#11 Kousuke Ebihara12年以上前に更新

  • ステータスPending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
  • 進捗率50 から 70 に変更

OK です。

http://redmine.openpne.jp/issues/2439#note-7 の問題についてはチケットを作成してください(軽く確認したところ、 diary_member_id_member_id の作成のための ALTER 文を実行するマイグレートスクリプトが見当たらず、いったいどのようにしてその現象を発生させたのかよくわかりませんでした)

#12 Mutsumi Imamura12年以上前に更新

Kousuke Ebihara は書きました:

OK です。

http://redmine.openpne.jp/issues/2439#note-7 の問題についてはチケットを作成してください(軽く確認したところ、 diary_member_id_member_id の作成のための ALTER 文を実行するマイグレートスクリプトが見当たらず、いったいどのようにしてその現象を発生させたのかよくわかりませんでした)

#2448 でチケットが作成されています

#13 Mutsumi Imamura12年以上前に更新

  • ステータス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)

#14 Yuya Watanabe12年以上前に更新

  • ステータスFixed(完了) から Pending Review(レビュー待ち) に変更
  • 進捗率100 から 50 に変更

レビュー,テスト終了してましたが,DQLの予約語やモデルの先頭を小文字にしていたため,下記コミットを行いました.

https://github.com/balibali/opDiaryPlugin/commit/21c2b98305869e1a3e93bb5b5d46436670003aa7

#15 Kousuke Ebihara12年以上前に更新

  • ステータスPending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
  • 進捗率50 から 70 に変更

#16 Yuya Watanabe12年以上前に更新

  • ステータスPending Testing(テスト待ち) から Pending Review(レビュー待ち) に変更
  • 進捗率70 から 50 に変更

note-14の状態で動作しなかったためDQLをSQLに書き直しました.

https://github.com/balibali/opDiaryPlugin/commit/c8d26bbe7a32f1d314f946e99bb3166f2c8c7d8d

#17 Kousuke Ebihara12年以上前に更新

  • ステータスPending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
  • 進捗率50 から 70 に変更

#18 Yuya Watanabe12年以上前に更新

  • ステータスPending Testing(テスト待ち) から Pending Review(レビュー待ち) に変更
  • 進捗率70 から 50 に変更

#19 Kousuke Ebihara12年以上前に更新

  • ステータスPending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
  • 進捗率50 から 70 に変更

#20 Mutsumi Imamura12年以上前に更新

再テストOKです。

#21 Mutsumi Imamura12年以上前に更新

  • ステータスPending Testing(テスト待ち) から Fixed(完了) に変更
  • 進捗率70 から 100 に変更

他の形式にエクスポート: Atom PDF