vBulletin 5データベースの移行 - インポートスクリプトのエラー

承知しました。簡単な要約です。

現在vBulletin 3を使用しているフォーラムの移行作業を手伝っています。
データベースのダンプ(20GB、はい、その通りです)から開始し、ステージング環境で作業しています。

vBulletin 5へのアップグレードを実行しました。5〜6時間かかりましたが、完了しました。バージョンはvBulletin 5.4です。
Discourseで受け入れられるように、ユーザー名のクリーニングを行いました。

次に、Docker Discourseをインストールし、こちらのガイドを参考に準備を進めました。参考にというのは、ほとんどが冗長または古い情報でしたが、何をすべきかの指針を得るのに役立ったからです。

現在、Rubyのコーディング経験がほとんどないため、完全に手探りの状態です。
関連する手順は、インストールの完了後、./launcher enter appでコンテナに入り、以下の操作を行いました。

  • freetds-devlibmariadb-devを追加しました。
  • php_serialize gemを追加するためにGemfileを編集しました。
  • シェルからexport IMPORT=1を実行して、インポート用の環境を設定しました。
  • discourseユーザーとしてbundle install --no-deployment --without test --without development --path vendor/bundleを実行しました。

エラーが発生しました。

You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.

If this is a development machine, remove the /var/www/discourse/Gemfile freeze
by running `bundle config unset deployment`.

The list of sources changed
The dependencies in your gemfile changed

You have added to the Gemfile:
* mysql2
* redcarpet
* php_serialize
* sqlite3 (~> 1.3, >= 1.3.13)
* ruby-bbcode-to-md
* reverse_markdown
* tiny_tds
* csv
* parallel

そこで、以下のコマンドを実行しました。

  • bundle config unset deploymentを実行し、再度前のコマンドを実行しました。
  • mysql2php_serializeの両方が存在することを確認しました(存在していました)。
  • 古いフォーラムのアバターを追加しました(添付ファイルのインポートはありません)。そして、それらのディレクトリの所有権をdiscourseユーザーの自身の/home/discourseに割り当てました。
  • script/import_scripts/vbulletin5.rbを編集して、DB接続の参照を変更しました。
  • discourseユーザーとしてbundle exec ruby script/import_scripts/vbulletin5.rbを実行しました。

これにより、こちらのDiscourseで言及されていたtzinfo Integer values not supportedに関するエラーが発生しました。

Loading existing groups...
Loading existing users...
Loading existing categories...
Loading existing posts...
Loading existing topics...

importing groups...
       41 / 41 (100.0%)  [2294 items/min]  ]
importing users
Traceback (most recent call last):
        15: from script/import_scripts/vbulletin5.rb:726:in `<main>'
        14: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
        13: from script/import_scripts/vbulletin5.rb:46:in `execute'
        12: from script/import_scripts/vbulletin5.rb:79:in `import_users'
        11: from /var/www/discourse/script/import_scripts/base.rb:916:in `batches'
        10: from /var/www/discourse/script/import_scripts/base.rb:916:in `loop'
         9: from /var/www/discourse/script/import_scripts/base.rb:917:in `block in batches'
         8: from script/import_scripts/vbulletin5.rb:98:in `block in import_users'
         7: from /var/www/discourse/script/import_scripts/base.rb:264:in `create_users'
         6: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
         5: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
         4: from /var/www/discourse/script/import_scripts/base.rb:265:in `block in create_users'
         3: from script/import_scripts/vbulletin5.rb:110:in `block (2 levels) in import_users'
         2: from script/import_scripts/vbulletin5.rb:718:in `parse_timestamp'
         1: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/tzinfo-2.0.5/lib/tzinfo/timezone.rb:575:in `utc_to_local'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/tzinfo-2.0.5/lib/tzinfo/timestamp.rb:138:in `for': Integer values are not supported (ArgumentError)

@Haddoq の提案は、Time.zone.at(@tz.utc_to_local(timestamp))Time.zone.at(timestamp)に変更することでした。

また、ユーザークエリにlastvisitを追加するように提案されました。そうしないと、別のエラーが発生するため、それも追加しました。

しかし、移行をbundle exec ruby script/import_scripts/vbulletin5.rbで実行すると、次のようになります。

Loading existing groups...
Loading existing users...
Loading existing categories...
Loading existing posts...
Loading existing topics...

importing groups...
       41 / 41 (100.0%)  [120217 items/min]
importing users
Traceback (most recent call last):
        13: from script/import_scripts/vbulletin5.rb:727:in `<main>'
        12: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
        11: from script/import_scripts/vbulletin5.rb:46:in `execute'
        10: from script/import_scripts/vbulletin5.rb:79:in `import_users'
         9: from /var/www/discourse/script/import_scripts/base.rb:916:in `batches'
         8: from /var/www/discourse/script/import_scripts/base.rb:916:in `loop'
         7: from /var/www/discourse/script/import_scripts/base.rb:917:in `block in batches'
         6: from script/import_scripts/vbulletin5.rb:80:in `block in import_users'
         5: from script/import_scripts/vbulletin5.rb:723:in `mysql_query'
         4: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:22:in `query'
         3: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.4/lib/mysql2/client.rb:147:in `query'
         2: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.4/lib/mysql2/client.rb:147:in `handle_interrupt'
         1: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.4/lib/mysql2/client.rb:148:in `block in query'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.4/lib/mysql2/client.rb:148:in `_query': You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CASE WHEN u.scheme='blowfish:10' THEN token (Mysql2::Error)
                 WHEN u.scheme='lega' at line 2

この時点で少し途方に暮れています。誰か助けてもらえませんか?

「Migration Vietnam」に参加したことがある @Canapin さんをメンションします。彼ならもっと詳しいかもしれません :heart:

8時間ぶっ通しで作業するのは良くないことが判明しました。

SELECT u.userid, u.username, u.homepage, u.usertitle, u.usergroupid, u.joindate, u.email, の最後に u.lastvisit を追加する際に、その後に , を追加し忘れていました。

Canapin、pingしてしまってすみません :frowning:

「いいね!」 1

承知いたしました。フォローアップの問題です。参照していたガイドには、登録プロセスが遅くなった場合に再開できると記載されていました。

しかし、再開したところ、Postgres DB にユーザーが既に存在するというエラーが発生しました。

私の不注意で、DB 内の id > 1 を持つすべてのユーザーを削除し(基本的に discobot、system、admin を残しました)、再起動しました。これによりインポートは続行されますが、以前作成されたすべてのユーザーのメールが「既に使用されている」とマークされてしまいます。

クリーンアップするにはどうすればよいですか?また、このプロセスでは、既に一致するユーザー名が存在する場合に挿入をスキップすべきではありませんか?

編集:usersemail_tokensuser_emails をクリアする必要があることがわかりました。

「いいね!」 1

残念ながら、以前のインポートで何を調整したかを記録していなかったので、ほとんど知識がありません。今では、このようなものを書くための個人的なDiscourseインスタンスがあります…もっと早くそうすべきでした!
実際にインポート作業をしているときは、インポート作業に熟練しています。

ユーザーを削除することについては、railsコンソールを介してUserDestroyerを使用したかったのかもしれません。

「いいね!」 2

素晴らしい、これは「本番」移行の際に覚えておきます。今のところ、実行手順書を作成しながら、プロセス全体のテスト実行をしているだけです :slight_smile:

「いいね!」 1

なぜそうしたのですか?スクリプトでそれらを異なる方法でインポートするように変更したのでなければ、再起動して、まだインポートされていないものをインポートさせるだけでよかったはずです。

やり直す必要がある場合は、バックアップを復元するか、データベースを削除して新しく作成する方がはるかに簡単です。

UserCustomFieldsテーブルにインポートIDが見つかるはずです。そのエラーがどのように発生したのか、私にはよくわかりません。

変更点はリストに記載したとおりです。あなたと同じように私も驚いていますが、スクリプトは進行せず、エラーが発生して停止してしまいます。

インポートを高速化する方法はありますか?

このコミュニティには9万人以上のユーザーがいますが、何らかの理由でインポート速度が低下しています。その理由が想像できません。

一晩中実行しましたが、ユーザーだけで 25123 / 95635 ( 26.3%) [42 items/min] です。

投稿はそれよりも桁違いに多いです。移行にはどのくらい時間がかかると予想されますか?数日?数週間?

RAMはどのくらいですか?それが問題の可能性が高いです。停止して再起動できます。

数週間かかることもありました。だからバルクインポーターが存在するのです。

RAMはわずか2GBです。テストマシンです。VMではなくローカルで実行し(RAM 16GBの方がずっと良いでしょうか?)、すべてをパッケージ化してから最終的にアップロードできると思います。

バルクインポーターについて詳しく教えていただけますか?初めて聞くのですが、「vBulletinからDiscourseへ移行する」とGoogleで検索したときには絶対に出てくるはずです :angry:

Frustrated Jason Segel GIF by NETFLIX

他のインポーターがすでに一部のユーザーを処理した場合でも、これを実行できますか、それともクリーンアップする必要がありますか?

試してみました。最悪の場合、動作しないでしょう。以下のようなエラーが繰り返し表示されます。

ERROR: no implicit conversion of nil into String
/var/www/discourse/script/bulk_import/base.rb:861:in `encode'
/var/www/discourse/script/bulk_import/base.rb:861:in `normalize_charset'
/var/www/discourse/script/bulk_import/base.rb:856:in `normalize_text'
script/bulk_import/vbulletin5.rb:123:in `block in import_users'
/var/www/discourse/script/bulk_import/base.rb:725:in `block (2 levels) in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/script/bulk_import/base.rb:723:in `block in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:196:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:722:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:340:in `create_users'
script/bulk_import/vbulletin5.rb:120:in `import_users'
script/bulk_import/vbulletin5.rb:63:in `execute'
/var/www/discourse/script/bulk_import/base.rb:100:in `run'
script/bulk_import/vbulletin5.rb:781:in `<main>'

おそらく、他のインポータが作成/作成を開始したユーザーとグループをクリーンアップする必要があると思われます。

データベースを再び操作する前に、きれいに処理してくれるRubyコマンドはありますか?

今回は、Discourseのインストールを破棄して再作成することにします。Dockerに感謝します。

いいえ、クリーンインストールしましたが、スクリプトは依然としてこの汎用的なエラーで失敗します。

ERROR: no implicit conversion of nil into String
/var/www/discourse/script/bulk_import/base.rb:861:in `encode'
/var/www/discourse/script/bulk_import/base.rb:861:in `normalize_charset'
/var/www/discourse/script/bulk_import/base.rb:856:in `normalize_text'
script/bulk_import/vbulletin5.rb:123:in `block in import_users'
/var/www/discourse/script/bulk_import/base.rb:725:in `block (2 levels) in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/script/bulk_import/base.rb:723:in `block in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:196:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:722:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:340:in `create_users'
script/bulk_import/vbulletin5.rb:120:in `import_users'
script/bulk_import/vbulletin5.rb:63:in `execute'
/var/www/discourse/script/bulk_import/base.rb:100:in `run'
script/bulk_import/vbulletin5.rb:781:in `<main>'

これをデバッグして、少なくともどの値が nil で、代わりに何かが期待されているのかを理解する方法はありますか?

わかりました、エラーはエンコーディングに関連しているようです。
bulk_import/vbulletin5.rb でエンコーディングを指定できます(この場合、UTF8mb4 ですが、base.rb ファイルでは、文字セットマップのいずれにもマッピングされていないようです。

こんにちは!

一般的なヒントをいくつかご紹介します。

  1. スクリプトに変更を加える場合は、最初からやり直すか、少なくとも既知の良い時点から始めることをお勧めします。@pfaffman が言ったように、移行を実行する直前に取得したバックアップを復元することで、最も簡単に実行できます。
  2. 一括インポートは一般的に時間がかかりませんが、この特定の一括インポートは、メモリ内にキャッシュするため、膨大な量の RAM を消費する可能性があります。私が実行した vBulletin の一括移行では、2GB の非圧縮 SQL ファイルから、プロセスに 22GB の RAM が必要でした(二重チェック済み、タイプミスではありません)。
  3. スクリプトに変更を加える場合は、各テーブルについて 100 または 1000 件のレコードを含む入力のテストバージョンを作成することをお勧めします(ただし、参照整合性に注意してください。つまり、他のテーブルから参照されているテーブルを切り捨てないでください)。8 時間以上かかるプロセスで変更をテストすると、すぐに正気を失うことになります。

スタックトレースに関するより具体的なヒント:実行した特定のファイルに言及している行を探してください。この場合はエンコーディングの問題ですが、より関連性が高いのは、ユーザー名に関する事実です。

ユーザー名をサニタイズする必要があったとのことですので、スクリプトで予期されているとおりにエンコードしたかどうかを再確認することをお勧めします。

「いいね!」 2

ディスコースを再作成するのではなく、データベースをドロップ、作成、マイグレーションできます。ただし、少しトリッキーです。

  sv stop unicorn

その後

  rake db:drop db:create db:migrate

エラーが表示され、rakeタスクの前に設定する必要があるENV変数を設定するように指示されます。

バックアップを復元することもできます。これはより便利です。

参考までに、バルクマイグレーションスクリプトを使用したことはありません。

「いいね!」 1

これはさらに奇妙です。ユーザー名はすべて、Discourseのガイドラインに従ってサニタイズされており、基本的に文字、数字、または_のみに変更され、それ以外は何も含まれていません。

いずれにせよ、文字セットをutf8mb4からデフォルトであったutf8に変更すると、処理は進みましたが、無効なメールアドレスのエラーが発生しています。

ERROR: can't modify frozen String: "24ef401b30f5161e5a0bb27ec49ed921@email.invalid"
/var/www/discourse/script/bulk_import/base.rb:457:in `downcase!'
/var/www/discourse/script/bulk_import/base.rb:457:in `process_user_email'
/var/www/discourse/script/bulk_import/base.rb:726:in `block (2 levels) in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/mysql2/alias_method.rb:8:in `each'
/var/www/discourse/script/bulk_import/base.rb:723:in `block in create_records'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/pg-1.4.5/lib/pg/connection.rb:196:in `copy_data'
/var/www/discourse/script/bulk_import/base.rb:722:in `create_records'
/var/www/discourse/script/bulk_import/base.rb:351:in `create_user_emails'
script/bulk_import/vbulletin5.rb:151:in `import_user_emails'
script/bulk_import/vbulletin5.rb:66:in `execute'
/var/www/discourse/script/bulk_import/base.rb:100:in `run'
script/bulk_import/vbulletin5.rb:781:in `<main>'

「非バルク」インポートでは、不正な形式のメールアドレスが検出されたものの自動的に置き換えられていたため、この件についてこれから調査します。

完了したら、空のまっさらなディスコースのインストールをバックアップしてください。
いつでもすぐに復元して、もう一度やり直すことができます。

「いいね!」 2

さらに、例えば投稿のインポートで問題が発生した場合、ユーザーのインポートが正常に完了した後にスクリプトを終了し、別のバックアップを作成することもできます。その後、スクリプトを再開し、ユーザーのインポートが完了した時点から再開できます。

「いいね!」 1