Bug(バグ) #3258
完了2 系で退会したメンバのデータが 3 系で新規登録したメンバに紐付いてしまう場合がある
100%
説明
概要¶
2 系で退会したはずのメンバのコメントが 3 系で新規登録したメンバによって書かれたかのような処理が行われる.
再現方法¶
日記コメントの場合.他のデータも紐付く可能性があるが未調査.
- 2.14 をインストール
- 初期メンバ A を登録(SNS メンバ数 1)
- メンバ B を追加(SNS メンバ数 2)
- メンバ C を追加(SNS メンバ数 3)
- メンバ A で日記 d を書く
- 日記 d に対して メンバ C がコメント x を書く
- メンバ C が退会する(SNS メンバ数 2)
- 3.6.3 へアップグレード
- 日記 d を閲覧する -> コメント x のメンバが非表示であることを確認する
- メンバ D を追加(SNS メンバ数 3)
- 日記 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)
ichikawa tatsuya さんが約12年前に更新
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;
ichikawa tatsuya さんが約12年前に更新
- ステータス を New(新規) から Accepted(着手) に変更
- 担当者 を ichikawa tatsuya にセット
ichikawa tatsuya さんが約12年前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
Yuya Watanabe さんが約12年前に更新
- トラッカー を Backport(バックポート) から Bug(バグ) に変更
- 3.6 で発生するか を Yes (はい) にセット
- 3.8 で発生するか を No (いいえ) にセット
Yuya Watanabe さんが約12年前に更新
メモを書き写してきた.
https://redmine.openpne.jp/issues/3074#note-4
他にも auto_increment の値が更新されないことによって発生しうる問題を調査する必要がある.
メンバについては 下記データが影響を受けるものとおもわれる.他にもあるかどうかは調査が必要.
- 日記コメント
- あしあと
- コミュニティトピックコメント
- コミュニティイベントコメント
Kousuke Ebihara さんが約12年前に更新
- ステータス を Pending Review(レビュー待ち) から 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 等のレベルでクエリを構築して実行するわけにはいかないでしょうか。
ichikawa tatsuya さんが約12年前に更新
- ステータス を Rejected(差し戻し) から Accepted(着手) に変更
- 進捗率 を 50 から 0 に変更
ichikawa tatsuya さんが約12年前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 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;'); + } +}
Kousuke Ebihara さんが約12年前に更新
- ステータス を Pending Review(レビュー待ち) から Rejected(差し戻し) に変更
レビュー対象となるコミットを示すか、もしくは共有リポジトリのリリースブランチにコミットを追加することによって、このチケットにコミットを紐づけてください。
ichikawa tatsuya さんが約12年前に更新
すみませんでした。
stable-3.6.xブランチで修正しました。コミットは以下です。
https://github.com/ichikawatatsuya/OpenPNE3/commit/9bb27331f8b7e98ab9b02bfb7a9626a56d953ffa
ichikawa tatsuya さんが約12年前に更新
- ステータス を Rejected(差し戻し) から Accepted(着手) に変更
- 進捗率 を 50 から 0 に変更
ichikawa tatsuya さんが約12年前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
Kousuke Ebihara さんが約12年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Mutsumi Imamura さんが約12年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更
動作確認OKです。