ترحيل قاعدة بيانات vBulletin 5 - أخطاء في سكربت الاستيراد

حسنًا، ملخص سريع.

أتطوع في ترحيل منتدى حاليًا على vbulletin3.
على بيئة اختبار، بدءًا من نسخة احتياطية لقاعدة البيانات (20 جيجابايت، نعم قرأت ذلك بشكل صحيح).

تشغيل الترقية إلى vBulletin 5. استغرق الأمر 5-6 ساعات ولكنه تم. الإصدار هو vBulletin 5.4.
قمت ببعض التنظيف لأسماء المستخدمين ليتم قبولها بواسطة discourse.

الآن، قمت بتثبيت docker discourse واتبعت هذا الدليل بشكل غير دقيق للإعداد. بشكل غير دقيق يعني أن معظمها كان زائدًا عن الحاجة أو قديمًا ولكنه ساعد في الحصول على بعض التوجيهات حول ما يجب فعله.

أنا في الخطوة التي أصبحت فيها أعمى حرفيًا لأن لدي خبرة برمجية في Ruby تكاد تكون صفرًا.
لذا، الأجزاء ذات الصلة، بعد الانتهاء من التثبيت دخلت الحاوية باستخدام ./launcher enter app ثم:

  • أضفت freetds-dev و libmariadb-dev
  • قمت بتحرير Gemfile لإضافة gem php_serialize.
  • من shell، قمت بتشغيل export IMPORT=1 لتعيين البيئة للاستيراد.
  • بصفتي مستخدم discourse قمت بتشغيل bundle install --no-deployment --without test --without development --path vendor/bundle

حصلت على الخطأ:

أنت تحاول التثبيت في وضع النشر بعد تغيير
ملف Gemfile الخاص بك. قم بتشغيل `bundle install` في مكان آخر وأضف
ملف Gemfile.lock المحدث إلى نظام التحكم في الإصدار.

إذا كان هذا جهاز تطوير، فقم بإزالة تجميد /var/www/discourse/Gemfile
عن طريق تشغيل `bundle config unset deployment`.

تغيرت قائمة المصادر
تغيرت التبعيات في ملف Gemfile الخاص بك

لقد أضفت إلى ملف 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 وتشغيل الأمر السابق مرة أخرى
  • تأكدت من وجود كل من mysql2 و php_serialize (كانا موجودين)
  • أضفت صور المنتدى القديمة (لا توجد مرفقات للاستيراد) وخصصت ملكية الدلائل لمستخدم discourse في /home/discourse الخاص به.
  • قمت بتحرير script/import_scripts/vbulletin5.rb لتغيير الإشارة للاتصال بقاعدة البيانات.
  • بصفتي المستخدم discourse قمت بتشغيل bundle exec ruby script/import_scripts/vbulletin5.rb

أعاد لي هذا خطأ بشأن tzinfo Integer values not supported الذي وجدته مذكورًا هنا في هذا المنتدى.

تحميل المجموعات الموجودة...
تحميل المستخدمين الموجودين...
تحميل الفئات الموجودة...
تحميل المشاركات الموجودة...
تحميل المواضيع الموجودة...

استيراد المجموعات...
       41 / 41 (100.0%)  [2294 عنصر/دقيقة]  ]
استيراد المستخدمين
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 هذا ما أحصل عليه:

تحميل المجموعات الموجودة...
تحميل المستخدمين الموجودين...
تحميل الفئات الموجودة...
تحميل المشاركات الموجودة...
تحميل المواضيع الموجودة...

استيراد المجموعات...
       41 / 41 (100.0%)  [120217 عنصر/دقيقة]
استيراد المستخدمين
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

في هذه المرحلة أنا ضائع قليلاً. هل يمكن لأحد المساعدة؟

تم الإشارة إلى @Canapin لأنه كان في “Migration Vietnam” وقد يعرف المزيد :heart:

العمل لمدة 8 ساعات متواصلة أمر سيء.

عند إضافة u.lastvisit في نهاية SELECT u.userid, u.username, u.homepage, u.usertitle, u.usergroupid, u.joindate, u.email, نسيت إضافة , بعدها.

آسف يا Canapin على الإزعاج :frowning:

إعجاب واحد (1)

حسناً، مشكلة متابعة. الدليل الذي كنت أتبعه ذكر أن عملية التسجيل يمكن إعادة تشغيلها إذا تباطأت.

ولكن عند إعادة التشغيل، أحصل على أخطاء حول وجود المستخدمين بالفعل في قاعدة بيانات postgres.

يا لي من أحمق، لقد ذهبت وحذفت جميع المستخدمين الذين لديهم id > 1 في قاعدة البيانات (مع ترك discobot والنظام والمسؤول بشكل أساسي) وأعدت التشغيل. هذا يجعل الاستيراد يستمر ولكن جميع رسائل البريد الإلكتروني للمستخدمين الذين تم إنشاؤهم سابقًا تم تمييزها على أنها “مستخدمة بالفعل” في مكان ما.

ما الذي يمكنني فعله لتنظيفها، وألا يجب أن تتخطى هذه العملية الإدراج إذا كان هناك بالفعل اسم مستخدم مطابق؟

تعديل: حسناً، اكتشفت أنني بحاجة إلى مسح users و email_tokens و user_emails.

إعجاب واحد (1)

للأسف، لم أتعقب ما كنت أقوم بتعديله في عمليات الاستيراد السابقة الخاصة بي، لذا لدي معرفة قليلة. لدي الآن مثيل Discourse شخصي حيث أكتب هذا النوع من الأشياء… كان يجب أن أفعل ذلك من قبل!
أنا أكثر مهارة في استيراد الأشياء عندما أعمل عليها بالفعل.

بالنسبة لتدمير المستخدمين، ربما كنت ترغب في استخدام UserDestroyer من خلال وحدة تحكم rails:

إعجابَين (2)

أشياء رائعة، سأضعها في الاعتبار عند إجراء الترحيل “الحقيقي”. في الوقت الحالي، أنا فقط أقوم بتجربة العملية بأكملها أثناء كتابة دليل تشغيل :slight_smile:

إعجاب واحد (1)

لماذا فعلت ذلك؟ ما لم تقم بتغيير شيء ما في البرنامج النصي الذي سيقوم باستيراد هؤلاء بشكل مختلف، فيجب عليك فقط إعادة التشغيل وجعله يستورد أولئك الذين لم يتم استيرادهم بالفعل.

إذا كنت بحاجة إلى البدء من جديد، فمن الأسهل بكثير استعادة نسخة احتياطية أو إسقاط قاعدة بيانات جديدة وإنشائها.

يجب أن يجد معرّفات الاستيراد في جدول UserCustomFields. لست متأكدًا تمامًا من كيفية حصولك على هذا الخطأ.

التغييرات هي التي أدرجتها. أنا متفاجئ مثلك ولكن النص البرمجي لم يتقدم وتوقف ببساطة بسبب خطأ.

هل هناك أي طريقة لتسريع الاستيراد؟

لدي أكثر من 90 ألف مستخدم في هذا المجتمع وسرعة الاستيراد تتدهور بمرور الوقت لسبب ما ولا أستطيع تخيل السبب.

لقد استمر طوال الليل وفقط للمستخدمين نحن عند 25123 / 95635 ( 26.3%) [42 عنصرًا/دقيقة]

هناك عدة مراتب من حيث الحجم من المشاركات. كم من الوقت يجب أن أتوقع حدوث الهجرة؟ أيام؟ أسابيع؟

ما مقدار ذاكرة الوصول العشوائي؟ هذه على الأرجح هي المشكلة. يمكنك التوقف وإعادة التشغيل.

لقد استغرقت أسابيع. لهذا السبب توجد مستوردات الدُفعات.

لديها 2 جيجابايت فقط من ذاكرة الوصول العشوائي. إنها آلة اختبار. يمكنني تشغيلها محليًا بدلاً من جهاز افتراضي (هل ستكون 16 جيجابايت من ذاكرة الوصول العشوائي أفضل بكثير؟) ثم حزم كل شيء وتحميله في النهاية على ما أعتقد.

هل يمكنك توضيح مستوردات الدُفعات؟ أول مرة أسمع عنها وبالتأكيد كان يجب أن تظهر عندما كنت أبحث عن “ترحيل vbulletin إلى discourse” على جوجل :angry:

صورة GIF لجيسون سيجل محبط من 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>'

أفترض أنه يجب عليّ تنظيف المستخدمين والمجموعات التي أنشأها المستورد الآخر أو بدأ في إنشائها.
قبل أن أعبث بقاعدة البيانات مرة أخرى، هل هناك أمر روبي يمكنني تشغيله يعتني بذلك بطريقة نظيفة؟

هذه المرة سأقوم فقط بتدمير وإعادة إنشاء تثبيت 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. ستستغرق المستوردات المجمعة عمومًا وقتًا أقل بكثير، ولكن هذه المستوردة المحددة لديها القدرة على استهلاك كميات هائلة من ذاكرة الوصول العشوائي لأنها تقوم بتخزين الأشياء مؤقتًا في الذاكرة. بالنسبة لترحيل vBulletin مجمع معين قمت به من ملف SQL بحجم 2 جيجابايت غير مضغوط، احتاجت العملية إلى 22 جيجابايت من ذاكرة الوصول العشوائي (تم التحقق مرة أخرى، ليس خطأ مطبعي).
  3. إذا أجريت تغييرات على البرنامج النصي، أقترح عليك إنشاء نسخة اختبار من الإدخال تحتوي على 100 أو 1000 سجل لكل جدول (ولكن انتبه لسلامة المراجع - أي لا تقم باقتطاع الجداول التي تشير إليها جداول أخرى). سيؤدي اختبار التغييرات بعملية تستغرق أكثر من 8 ساعات إلى تآكل سلامتك العقلية بسرعة كبيرة.

نصيحة أكثر تحديدًا حول تتبعات المكدس: ابحث عن الأسطر التي تذكر الملف المحدد الذي قمت بتشغيله. في هذه الحالة، نعم إنها مشكلة ترميز، ولكن الأكثر أهمية هو حقيقة أنها تتعلق بأسماء المستخدمين:

لقد ذكرت أنك اضطررت إلى تنقية أسماء المستخدمين، لذا سأتحقق مرة أخرى من أنك قمت بترميزها كما هو متوقع من قبل البرنامج النصي.

إعجابَين (2)

يمكنك فقط إسقاط قاعدة البيانات وإنشائها وترحيلها بدلاً من إعادة إنشاء Discourse. الأمر صعب بعض الشيء، حيث يتعين عليك

  sv stop unicorn

ثم

  rake db:drop db:create db:migrate

سيشتكي ويخبرك بتعيين متغير بيئة تحتاج إلى وضعه في السطر قبل مهمة rake.

يمكنك أيضًا استعادة نسخة احتياطية، والتي يمكن أن تكون أكثر ملاءمة.

على سبيل المثال، لم أستخدم أبدًا نصًا برمجيًا لترحيل جماعي.

إعجاب واحد (1)

هذا أغرب لأن أسماء المستخدمين تم تنظيفها بالكامل لتتوافق مع إرشادات ديسكورس، وبشكل أساسي تم تغييرها جميعًا لتكون أحرفًا أو أرقامًا أو _، لا شيء آخر.

في كل الأحوال، تغيير ترميز الأحرف من 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>'

سأذهب الآن لاكتشاف ما يتعلق بهذا حيث أن الاستيراد “غير المجمع” كان يكتشف بعض رسائل البريد الإلكتروني المشوهة ولكنه يستبدلها تلقائيًا.

بعد الانتهاء من ذلك، قم بإنشاء نسخة احتياطية من تثبيت Discourse الفارغ والنظيف الخاص بك.
يمكنك دائمًا استعادة ذلك بسرعة والبدء من جديد.

إعجابَين (2)

لإضافة إلى ذلك، إذا واجهت مشكلة، على سبيل المثال، في استيراد المشاركات، يمكنك أيضًا إنهاء البرنامج النصي بعد اكتمال استيراد المستخدمين بنجاح وإنشاء نسخة احتياطية أخرى. ثم يمكنك إعادة تشغيل البرنامج النصي ويمكنك الاستئناف في اللحظة التي قمت فيها بالفعل باستيراد المستخدمين.

إعجاب واحد (1)