Project

General

Profile

Bug(バグ) #3258

2 系で退会したメンバのデータが 3 系で新規登録したメンバに紐付いてしまう場合がある

Added by Chiharu Nakajima almost 8 years ago. Updated about 5 years ago.

Status:
Fixed(完了)
Priority:
Normal(通常)
Target version:
Start date:
2012-11-12
Due date:
% Done:

100%

3.6 で発生するか:
Yes (はい)
3.8 で発生するか:
No (いいえ)

Description

概要

2 系で退会したはずのメンバのコメントが 3 系で新規登録したメンバによって書かれたかのような処理が行われる.

再現方法

日記コメントの場合.他のデータも紐付く可能性があるが未調査.

  1. 2.14 をインストール
  2. 初期メンバ A を登録(SNS メンバ数 1)
  3. メンバ B を追加(SNS メンバ数 2)
  4. メンバ C を追加(SNS メンバ数 3)
  5. メンバ A で日記 d を書く
  6. 日記 d に対して メンバ C がコメント x を書く
  7. メンバ C が退会する(SNS メンバ数 2)
  8. 3.6.3 へアップグレード
  9. 日記 d を閲覧する -> コメント x のメンバが非表示であることを確認する
  10. メンバ D を追加(SNS メンバ数 3)
  11. 日記 d を閲覧する -> コメント x が メンバ D によって書かれたことになっている

確認バージョン

バージョンアップ前: OpenPNE 2.14
バージョンアップ後: OpenPNE 3.6.3

CentOS 5.8
MySQL 5.0.95

原因

メンバのデータを表すテーブルの auto_increment の値が 2.14 のときのものと一致していないため,新規登録した場合に 2 系ですでに使われていた メンバID に数字が割り当てられてしまう.

mysql> show table status where name = "c_member";
+----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| Name     | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options | Comment |
+----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
| c_member | MyISAM |      10 | Dynamic    |    2 |             64 |         128 | 281474976710655 |         3072 |         0 |              4 | 2012-06-11 01:28:50 | 2012-06-11 01:28:50 | NULL       | utf8_general_ci |     NULL |                |         | 
+----------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+---------+
1 row in set (0.00 sec)

mysql> show table status where name = "member";
+--------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+----------------------------------------------------------------------------------+
| Name   | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment                                                                          |
+--------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+----------------------------------------------------------------------------------+
| member | InnoDB |      10 | Compact    |    2 |           8192 |       16384 |               0 |        32768 |         0 |              3 | 2012-06-11 01:28:50 | NULL        | NULL       | utf8_unicode_ci |     NULL |                | Saves informations of members; InnoDB free: 1845248 kB; (`invite_member_id`) REF | 
+--------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+----------------------------------------------------------------------------------+
1 row in set (0.00 sec)


Related issues

Related to OpenPNE 3 - Bug(バグ) #3074: 2 系で退会したメンバのデータが 3 系で新規登録したメンバに紐付いてしまう場合がある Invalid(無効) 2012-06-11

Associated revisions

Revision 8966e1d8 (diff)
Added by ichikawa tatsuya almost 8 years ago

(refs #3258)fixed a bug where auto-increment is shifted.

Revision 7b66af7a (diff)
Added by ichikawa tatsuya almost 8 years ago

(refs #3258)fixed upgrade sql bug.

History

#1 Updated by ichikawa tatsuya almost 8 years ago

c_memberテーブルのオートインクリメントの値をmemberテーブルへ引き継ぐよう修正。
https://github.com/ichikawatatsuya/OpenPNE3/commit/516b397435f0602879b43d49088f95580bfc296c

diff --git data/upgrade/2/sql/member_basic.sql data/upgrade/2/sql/member_basic.sql
index 4766c81..304045b 100644
--- data/upgrade/2/sql/member_basic.sql
+++ data/upgrade/2/sql/member_basic.sql
@@ -1,3 +1,8 @@
 INSERT INTO member (id, name, is_active, is_login_rejected, created_at, updated_at) (SELECT c_member_id, nickname, 1, is_login_rejected, r_date, u_datetime FROM c_member);
+INSERT INTO c_member value("","","","","","","","","","","","","","","","","","","","","","","","","","");
+SET @lastId = (SELECT last_insert_id());
+SET @auto_inc_query = CONCAT('ALTER TABLE member AUTO_INCREMENT = ', @lastId);
+PREPARE query_prepare FROM @auto_inc_query;
+EXECUTE query_prepare;
 UPDATE member, c_member SET invite_member_id = c_member_id_invite WHERE id = c_member_id AND c_member_id_invite <> 0;

#2 Updated by ichikawa tatsuya almost 8 years ago

  • Status changed from New(新規) to Accepted(着手)
  • Assignee set to ichikawa tatsuya

#3 Updated by ichikawa tatsuya almost 8 years ago

  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)
  • % Done changed from 0 to 50

#4 Updated by Yuya Watanabe almost 8 years ago

  • Tracker changed from Backport(バックポート) to Bug(バグ)
  • 3.6 で発生するか set to Yes (はい)
  • 3.8 で発生するか set to No (いいえ)

#5 Updated by Yuya Watanabe almost 8 years ago

メモを書き写してきた.

https://redmine.openpne.jp/issues/3074#note-4

他にも auto_increment の値が更新されないことによって発生しうる問題を調査する必要がある.

メンバについては 下記データが影響を受けるものとおもわれる.他にもあるかどうかは調査が必要.
  • 日記コメント
  • あしあと
  • コミュニティトピックコメント
  • コミュニティイベントコメント

#6 Updated by Kousuke Ebihara almost 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Rejected(差し戻し)

差し戻します。以下の説明を読んで、修正方法について再度検討しなおしてください。

AUTO_INCREMENT の取得方法について

c_member テーブルのレコードは、 OpenPNE 3 のデータベースには (まだ) 入れることのできない情報を持っているために、アップグレードが終わっても c_member テーブルの削除処理をおこなっていません。

c_member テーブルは今後も使用する可能性があるため、ダミーのデータを挿入したのち、そのデータを削除していないことは問題です。

また、できるだけ無用なデータ操作処理を伴わない形で実現できないかについても再考してください。

アップグレードに関しては MySQL に依存していても問題ありません。ということで、以下の手段によって AUTO_INCREMENT を取得することができます。

  • SHOW TABLE STATUS LIKE "c_member" によって得られたレコードの、 Auto_increment カラムを取得する
  • SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_NAME='c_member' AND TABLE_SCHEMA = DATABASE(); によって取得する

ただし後者は information_schema を利用する関係で、 MySQL 5.1 以降でしか使えない手ということになり、採用することができません。前者は OpenPNE がサポートするバージョンよりも古い MySQL でも利用可能だと思いますが、もし採用する場合は念のため確認をお願いします。

AUTO_INCREMENT の設定方法について

PREPARE 文や EXECUTE 文は MySQL 5.1 の新機能であり、 5.1 未満のバージョンでは利用できません。

http://bugs.mysql.com/bug.php?id=20665#c92132

[10 Nov 2006 18:05] Paul DuBois

Clarification: The additional statements are supported both
for SQL syntax for prepared statements (PREPARE/EXECUTE)
and by the binary protocol. The additional supported statements
are noted in both these places:

http://dev.mysql.com/doc/refman/5.1/en/sqlps.html
http://dev.mysql.com/doc/refman/5.1/en/c-api-prepared-statements.html

http://dev.mysql.com/doc/refman/5.1/en/news-5-1-12.html

The following statements now can be executed as prepared statements (using PREPARE plus EXECUTE):

OpenPNE 3 がサポートする MySQL は 4.1 以降であると doc/ja/OpenPNE3_Setup_Guide.txt 等に明示されていますから、少なくとも安定版においては MySQL 4.1 でも動作する形での対応をおこなわなければなりません。

おそらく PREPARE 文と EXECUTE 文を使わないことには MySQL のみで対応をおこなうことは難しいと思います。今回の場合は無理して SQL のみで完結させる必要はないと思うので、 PHP 等のレベルでクエリを構築して実行するわけにはいかないでしょうか。

#7 Updated by ichikawa tatsuya almost 8 years ago

  • Status changed from Rejected(差し戻し) to Accepted(着手)
  • % Done changed from 50 to 0

#8 Updated by ichikawa tatsuya almost 8 years ago

  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)
  • % Done changed from 0 to 50

Mysql4.1以降で動作する機能のみを使用するように修正しました。
(SHOW TABLE STATUS はバージョン3.23で導入された機能なので問題ありませんでした)

また、MysqlのみではAuto_incrementの値を取得できないためPHPを使用するよう変更しました。

diff --git data/upgrade/2/definition.yml data/upgrade/2/definition.yml
index 7b5e651..25e83f7 100644
--- data/upgrade/2/definition.yml
+++ data/upgrade/2/definition.yml
@@ -8,7 +8,8 @@ create_tables:
   strategy: CreateTable

 member_basic:
-  strategy: SQLImport
+  strategy: opUpgradeFrom2MemberStrategy
+  file: %SF_DATA_DIR%/upgrade/2/opUpgradeFrom2MemberStrategy.class.php

 files:
   strategy: SQLImport
diff --git data/upgrade/2/opUpgradeFrom2MemberStrategy.class.php data/upgrade/2/opUpgradeFrom2MemberStrategy.class.php
new file mode 100644
index 0000000..721a0ec
--- /dev/null
+++ data/upgrade/2/opUpgradeFrom2MemberStrategy.class.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * This file is part of the OpenPNE package.
+ * (c) OpenPNE Project (http://www.openpne.jp/)
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file and the NOTICE file that were distributed with this source code.
+ */
+
+/**
+ * The upgrating strategy by importing member.
+ *
+ * @package    OpenPNE
+ * @subpackage task
+ * @author     tatsuya ichikawa <ichikawa@tejimaya.com>
+ */
+class opUpgradeFrom2MemberStrategy extends opUpgradeAbstractStrategy
+{
+  public function run()
+  {
+    $this->getDatabaseManager();
+    $this->conn = Doctrine_Manager::connection();
+
+    $this->conn->beginTransaction();
+    try
+    {
+      $this->doRun();
+
+      $this->conn->commit();
+    }
+    catch (Exception $e)
+    {
+      $this->conn->rollback();
+
+      throw $e;
+    }
+  }
+
+  public function doRun()
+  {
+    $this->conn->execute('INSERT INTO member (id, name, is_active, is_login_rejected, created_at, updated_at) (SELECT c_member_id, nickname, 1, is_login_rejected, r_date, u_datetime FROM c_member)');
+
+    $tableStatus = $this->conn->fetchArray('SHOW TABLE STATUS LIKE "c_member"');
+    $autoIncrement = $tableStatus[10];
+    $this->conn->execute("ALTER TABLE member AUTO_INCREMENT = $autoIncrement");
+    $this->conn->execute('UPDATE member, c_member SET invite_member_id = c_member_id_invite WHERE id = c_member_id AND c_member_id_invite <> 0;');
+  }
+}

#9 Updated by Kousuke Ebihara almost 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Rejected(差し戻し)

レビュー対象となるコミットを示すか、もしくは共有リポジトリのリリースブランチにコミットを追加することによって、このチケットにコミットを紐づけてください。

#10 Updated by ichikawa tatsuya almost 8 years ago

すみませんでした。
stable-3.6.xブランチで修正しました。コミットは以下です。

https://github.com/ichikawatatsuya/OpenPNE3/commit/9bb27331f8b7e98ab9b02bfb7a9626a56d953ffa

#11 Updated by ichikawa tatsuya almost 8 years ago

  • Status changed from Rejected(差し戻し) to Accepted(着手)
  • % Done changed from 50 to 0

#12 Updated by ichikawa tatsuya almost 8 years ago

  • Status changed from Accepted(着手) to Pending Review(レビュー待ち)
  • % Done changed from 0 to 50

#13 Updated by Kousuke Ebihara almost 8 years ago

  • Status changed from Pending Review(レビュー待ち) to Pending Testing(テスト待ち)
  • % Done changed from 50 to 70

#14 Updated by Mutsumi Imamura almost 8 years ago

  • Status changed from Pending Testing(テスト待ち) to Fixed(完了)
  • % Done changed from 70 to 100

動作確認OKです。

Also available in: Atom PDF