Как перейти с MongoDB на MySQL

база данных MySQL MongoDB модульный тест

На самом деле, я занимаюсь миграцией базы данных уже больше месяца, проект, который я сейчас разрабатываю, фактически использовал MySQL в качестве основной базы данных в древние времена, позже, по некоторым причинам бизнеса, я мигрировал с MySQL на MongoDB и использовал несколько After несколько месяцев, поскольку служба базы данных очень нестабильна и необслуживаема, а сама MongoDB представляет собой базу данных без схемы, проблема грязных данных в базе данных очень серьезна. В настоящее время у членов команды нет богатого опыта разработки на Rails, поэтому они все еще надеются использовать ActiveRecord и Migration для наложения жестких ограничений на данные для обеспечения легальности данных в базе данных.

mysql-and-mongodb

В этой статье будут представлены некоторые проблемы, с которыми столкнулся автор в процессе переноса базы данных, и предоставлены читателям необходимые сведения.НеисправностьВыполнимое решение для переноса базы данных, если вам нужно перенести базу данных без простоев или вам нужны другие решения, представленное здесь решение предназначено для MongoDB с объемом данных в миллионы, расчетное время простоя составляет около двух часов, если объем данных находится на уровне уровень десятков миллионов Выше чрезмерное время простоя может быть неприемлемым, и должен быть разработан план непрерывной миграции; в любом случае, автор надеется, что эта статья может принести некоторые идеи разработчикам, которые хотят выполнить миграцию базы данных, и избежать некоторых подводные камни.

От отношения к документу

Хотя основное внимание в этой статье уделяется миграции с MongoDB на MySQL, автор все же хочет кратко упомянуть миграцию с MySQL на MongoDB.Если мы просто импортируем все данные из MySQL в MongoDB, на самом деле это относительно простое дело. важная причина в том, чтоТипы данных, поддерживаемые MySQL, являются подмножеством MongoDB.:

mongodb-mysql-datatype-relation

В процессе миграции все данные в MySQL можно экспортировать в формате csv, после чего можно будет использовать все данные в формате csv.mongoimportВсе импортировано в MongoDB:

$ mysqldump -u<username> -p<password> \
    -T <output_directory> \
    --fields-terminated-by ',' \
    --fields-enclosed-by '\"' \
    --fields-escaped-by '\' \
    --no-create-info <database_name>

$ mongoimport --db <database_name> --collection <collection_name> \
    --type csv \
    --file <data.csv> \
    --headerline

Хотя весь процесс кажется очень простым всего двумя командами, вы столкнетесь с массой проблем, когда очень захотите это сделать.У автора нет опыта миграции с MySQL или других реляционных баз данных на MongoDB, но в гугле есть много актуальной информации, так что это всегда проблема, на которую наступали бесчисленные предшественники, и опыт предшественников также может помочь нам сэкономить много времени.

mysql-to-mongodb

Использование csv для экспорта данных не вызовет проблем в большинстве случаев, но если какие-то документы в БД хранят форматированный текст, то хотя при экспорте данных проблем не будет, но при финальном импорте могут возникнуть некоторые проблемы.Довольно странная ошибка.

От документа к отношениям

По сравнению с миграцией с MySQL на MongoDB, обратная миграция более чем удваивает проблему, главным образом потому, что в MySQL не существует связи между многими типами данных и коллекциями в MongoDB, такими как встроенные данные. В реализации типов коллекций, таких как структуры , массивы и хэши, а также отношения "многие ко многим", многие проблемы не могут быть решены только путем переноса данных. Перед переносом данных необходимо реконструировать некоторые структуры данных. Эта статья Во второй половине этого раздела будут представлены структуры данных и логика, которые необходимо обработать.

mongodb-mysql-problems-to-be-solved

Прежде чем мы будем готовы полностью перенести базу данных на MySQL, нам необходимо выполнить некоторую подготовительную работу, чтобы максимально сократить работу, необходимую для окончательной миграции, чтобы гарантировать, что время простоя не будет слишком долгим. максимально исключить сложные данные в проекте.

предварительная обработка данных

Перед миграцией нужно выполнить большую подготовку, первое, что нужно сделать, это изменить все встроенные структуры данных на невстроенные структуры данных:

embedded-reference-documents

то есть положить всеembeds_manyа такжеembeds_oneотношения меняются наhas_manyа такжеhas_one, в то время какembedded_inзаменены наbelongs_toВ то же время нам нужно изменить соответствующие тесты в проекте на это эталонное отношение, но только изменение отношения в коде на самом деле не меняет данные в MongoDB.

def embeds_many_to_has_many(parent, child)
  child_key_name = child.to_s.underscore.pluralize
  parent.collection.find({}).each do |parent_document|
    next unless parent_document[child_key_name]
    parent_document[child_key_name].each do |child_document|
      new_child = child_document.merge "#{parent.to_s.underscore}_id": parent_document['_id']
      child.collection.insert_one new_child
    end
  end
  parent.all.unset(child_key_name.to_sym)
end

embeds_many_to_has_many(Person, Address)

Мы можем использовать приведенный выше код для преобразования всех встроенных моделей в ссылки, выравнивая все сложные отношения данных.Время выполнения этого кода зависит от количества двух моделей во встроенных отношениях.Следует отметить, что в MongoDB данные, встроенные в модель может показаться одинаковой по какой-то причине_idКонфликты могут вызвать сбой при вставке, вы можетеinsert_oneиспользоватьresuceЧтобы гарантировать, что выполнение этого кода не остановится по вышеуказанным причинам.

embedded-to-reference

С помощью этого кода мы можем легко расширить все исходные встроенные отношения в ссылочные отношения и превратить встроенные отношения в ссылки.Кроме этих двух изменений, нам не нужно делать другие вещи, будь то запрос данных.Создание модели не нужно менять реализацию кода, но помните, что внешний ключ родительской модели должен быть в дочерней моделидобавить индекс, в противном случае это приведет к тому, что родительская модель вызоветполное сканирование таблицы:

class Comment
  include Mongoid::Document
  index post_id: 1
  belongs_to :post
end

После того, как мы разобрались с уникальными встроенными отношениями в MongoDB, нам нужно решить некоторые сложные типы коллекций, такие как массивы и хэши, если мы используем MySQL 5.7 или PostgreSQL, нам не нужно с ними разбираться, т.к. последние версии MySQL и PostgreSQL уже поддерживает JSON, но автор превратил в проекте и массивы, и хэши в общие структуры данных.

В этом необязательном процессе на самом деле нет стандартного ответа Мы можем конвертировать разные данные в разные структуры данных по мере необходимости:

array-to-string-or-relation

Например, преобразование массива в строку или отношение «один ко многим», преобразование хэша в пару «ключ-значение» текущего документа и т. д., как обращаться с этими данными коллекции, на самом деле зависит от нашей бизнес-логики. изменяя эти поля, старайтесь быть как Верхний слой обеспечивает прямое.tagsили.categoriesAPI с тем же результатом:

class Post
  ...
  def tag_titles
    tags.map(&:title)
  end
  
  def split_categories
    categories.split(',')
  end
end

Этот шаг на самом деле необязателен. Приведенный выше код предназначен только для уменьшения нагрузки по модификации в других местах. Конечно, если вы хотите использовать базу данных MySQL 5.7 или PostgreSQL для поддержки JSON, большой проблемы нет, но есть некоторые проблемы при запросе поля сбора неудобно.

«Младшие братья» монгоида

Некоторые связанные плагины неизбежно будут использоваться во время разработки с Mongoid, напримерmongoid-enum,mongoid-slugа такжеmongoid-historyи т.д. Эти плагины реализованы с Плагины с одинаковым функционалом в ActiveRecord имеют очень разные реализации.

Для некоторых плагинов, таких как mongoid-slug, он вставляется только в документ модели, которая представила плагин._slugsполя, нам нужно только игнорировать эти добавленные поля во время переноса данных и заменить все#slugметод изменен на#id, никаких других изменений во время предварительной обработки не требуется. Реализация перечисления полностью отличается в плагине Mongoid и ActiveRecord:

mongodb-mysql-enu

mongoid-enum использует строки и_statusдля хранения полей типа перечисления, в то время как ActiveRecord использует целые числа иstatusПредставляет тип перечисления. У них есть некоторые различия в хранении базовой структуры данных. Мы решим эту проблему в более позднем сценарии миграции.

mongoid-activerecord-enum

Если в проекте используется много плагинов Mongoid из-за их разных реализаций, мы можем только решить, как их мигрировать в соответствии с конкретной реализацией разных плагинов.Если используются некоторые плагины, поддерживающие специальные функции , это может быть сложно реализовать в ActiveRecord. Найдите соответствующую поддержку и рассмотрите возможность временного удаления некоторых неважных функций при миграции.

Первичный ключ и UUID

Еще одна важная причина, по которой мы хотим перейти с MongoDB на MySQL, заключается в том, что первичный ключ каждого документа в MongoDB слишком подробный, 32-байтовый первичный ключ._idНе может предоставить нам много информации, это может только увеличить нашу дислексию, а кластер MongoDB не развернут в проекте, поэтому мы не можем воспользоваться преимуществами использования механизма генерации UUID по умолчанию.

mongodb-mysql-id

Мы не только не воспользовались преимуществами UUID, но и доставили нам много проблем в процессе миграции MySQL, с одной стороны, из-за того, что первичный ключ ActiveRecord по умолчанию является целым числом и не поддерживает UUID. с длиной байта 32. Мы не хотим менять UUID MongoDB, и нет проблем с переносом его непосредственно в MySQL, но нам нужно изменить первичный ключ целочисленного типа по умолчанию на строковый тип, и в то же время используйте генератор UUID, чтобы убедиться, что все первичные ключи увеличиваются по времени и не конфликтуют.

Если вы собираетесь использовать метод генератора UUID плюс, это на самом деле сэкономит много времени на миграцию, но не кажется особенно элегантным.Как выбрать, все еще нужно взвесить и оценить, но если мы решим использоватьintegerКогда используется тип самоинкрементного первичного ключа, необходимо проделать много дополнительной работы, во-первых, добавить все таблицы.uuidполя, как для всех внешних ключей, например.post_idсоздать соответствующийpost_uuidполе, черезuuidСоотнесите два:

mysql-before-migrations

В процессе переноса данных мы_idсопоставить сuuidсередина,post_idсопоставить сpost_uuidна, мы держимuuidа такжеpost_uuidСвязь между моделями гарантирует, что связь между моделями не будет потеряна в процессе переноса данных.idа такжеpost_idНет абсолютно никакой связи.

когда мы следуем_idПорядок проходит через весь документ, и когда данные в документе вставляются в таблицу, MySQL автоматически генерирует инкрементный первичный ключ для всех строк данных.id,а такжеpost_idНа данный момент все пусто.

mysql-after-migrations

После того, как все данные были вставлены в MySQL, мы передаем#find_by_uuidзапрос будетuuidа такжеpost_uuidОтношения в Migrate toidа такжеpost_id, и будет сочетаться сuuidВсе соответствующие поля удаляются, чтобы мы могли гарантировать, что связь между моделями не исчезнет, ​​а взаимное расположение строк данных будет точно таким же, как и до миграции.

миграция кода

Монгоид используетсяincludeЗагружайте соответствующие методы в текущую модель, а ActiveRecord делает это через наследование.ActiveRecord::BaseПосле завершения предварительной обработки данных мы можем изменить код существующего слоя модели.

Во-первых, конечно, изменить «родительский класс» модели, поставить всеMongoid::Documentизменился наActiveRecord::Base, а затем создайте файл миграции, соответствующий классу:

# app/models/post.rb
class Post < ActiveRecord::Base
  validate_presence_of :title, :content
end

# db/migrate/20170908075625_create_posts.rb
class CreatePosts < ActiveRecord::Migration[5.1]
  def change
    create_table :posts do |t|
      t.string :title, null: false
      t.text :content, null: false
      t.string :uuid, null: false

      t.timestamps null: false
    end
    
    add_index :posts, :uuid, unique: true
  end
end

Примечание. Чтобы добавить строку типа в каждую таблицуuuidполе, такжеuuidСоздайте уникальный индекс для ускорения прохожденияuuidСкорость построения взаимосвязей между разными моделями данных.

В дополнение к созданию файла миграции для базы данных и модификации базового класса нам также необходимо изменить некоторыеincludeмодули и запросы, уникальные для Mongoid, такие как использованиеgteилиlteЗапросы даты и запросы, которые используют регулярные выражения для сопоставления с образцом, эти запросы используются в ActiveRecord совершенно по-другому, чем в Mongoid, и нам нужно решать эти проблемы с помощью написанного от руки SQL.

mongoid-to-activerecord-model-and-query

Кроме того, нам также нужно иметь дело с некоторыми сложными модельными отношениями, такими как Mongoid вinverse_ofвызывается в ActiveRecordforeign_keyПодождите, эти модификации на самом деле не сложные, но если вы хотите разобраться со всем кодом в этой части, вам нужно детально протестировать бизнес-логику, чтобы убедиться, что не останется проблем, что также является тестом нашего проекта. Покрытие предъявляет относительно высокие требования, но я считаю, что большинство проектов Rails имеют очень хорошее тестовое покрытие, которое может гарантировать плавную миграцию этой части кода и логики, но если в проекте нет теста или тестовое покрытие очень высокое низкое, вы можете испытать только человеческую плоть или искать больше благословений, илиНе делайте миграций, пишите больше тестов и учитывайте эти рефакторинги..

перенос данных

Создание соответствующего файла миграции для каждой модели и построение таблицы на самом деле является ручной работой, которую необходимо выполнить.Хотя есть некоторые задачи, которые мы не можем пропустить, мы можем рассмотреть возможность автоматизации всех моделей.uuidполей и индексов, но и для подобныхpost_idполя добавляют соответствующиеpost_uuidСписок:

class AddUuidColumns < ActiveRecord::Migration[5.1]
  def change
    Rails.application.eager_load!
    ActiveRecord::Base.descendants.map do |klass|
      # add `uuid` column and create unique index on `uuid`.
      add_column klass.table_name, :uuid, :string, unique: true
      add_index klass.table_name, unique: true
      
      # add `xxx_uuid` columns, ex: `post_uuid`, `comment_uuid` and etc.
      uuids = klass.attribute_names
        .select { |attr| attr.include? '_id' }
        .map    { |attr| attr.gsub '_id', '_uuid' }
      next unless uuids.present?
      uuids.each do |uuid|
        add_column klass.table_name, uuid, :string
      end
    end
  end
end

в добавленииuuidПосле того, как столбцы и индексы установлены, мы можем начать миграцию базы данных.Если мы решим изменить первичный ключ исходных данных в процессе миграции, мы разделим миграцию на два этапа: миграция данных и восстановление отношений, бывший относится только к переносу всех данных в MongoDB в соответствующую таблицу в MySQL и передаче всех данных в соответствующую таблицу в MySQL._idПеревести вuuid,xx_idПеревести вxx_uuid, а последний упоминался ранее: byuuidа такжеxx_uuidАссоциация восстанавливает отношения между моделями и в конце удаляет всеuuidполе.

Мы можем использовать следующий код для миграции данных.Этот код просматривает все данные в коллекции из MongoDB, а затем передает документ в качестве параметра в блок, а затем передаетDatabaseTransformer#delete_obsolete_columnsа такжеDatabaseTransformer#update_rename_columnsМетод удаляет некоторые существующие столбцы, обновляет некоторые столбцы данных и, наконец, помещает всеidстолбцы становятсяuuid:

module DatabaseTransformer
  def import(collection_name, *obsolete_columns, **rename_columns)
    collection = Mongoid::Clients.default.collections.select do |c|
      c.namespace == "#{database}.#{collection_name.to_s.pluralize}"
    end.first

    unless collection.present?
      STDOUT.puts "#{collection_name.to_s.yellow}: skipped"
      STDOUT.puts
      return
    end

    constant = collection_name.to_s.singularize.camelcase.constantize
    reset_callbacks constant

    DatabaseTransformer.profiling do
      collection_count = collection.find.count
      collection.find.each_with_index do |document, index|
        document = yield document if block_given?
        delete_obsolete_columns document, obsolete_columns
        update_rename_columns document, rename_columns
        update_id_columns document

        insert_record constant, document
        STDOUT.puts "#{index}/#{collection_count}\n" if (index % 1000).zero?
      end
    end
  end
end

После выполнения различных операций над документом этот метод будет вызываться напрямуюDatabaseTransformer#insert_recordВставьте данные в соответствующую таблицу в MySQL; мы можем напрямую использовать следующий код для переноса всех документов в коллекции в MySQL:

transformer = DatabaseTransformer.new 'draven_production'
transformer.import :post, :_slugs, name: :title, _status: :status

Приведенный выше код будет объединять каждый документ_slugsвсе поля игнорируются, аnameпереименован вtitle,_statusпереименован вstatus, хотя поле mongoid-enum как тип перечисления полностью отличается от типа перечисления ActiveRecord, здесь нет проблем с прямой вставкой, модель ActiveRecord сама обработает преобразование между строками и целыми числами при ее создании:

def insert_record(constant, params)
  model = constant.new params
  model.save! validate: false
rescue Exception => exception
  STDERR.puts "Import Error: #{exception}"
  raise exception
end

Чтобы ускорить вставку данных и избежать всех побочных эффектов операций вставки, мы сбрасываем все обратные вызовы во время переноса данных:

def reset_callbacks(constant)
  %i(create save update).each do |callback|
    constant.reset_callbacks callback
  end
end

Функция этого кода вступит в силу только во время работы скрипта и не окажет никакого влияния на другие части проекта; в то же время скрипт будет печатать текущий прогресс в стандартный вывод после того, как каждая 1000 моделей будет успешно завершена. Помогите нам быстро определить проблемы и оценить время миграции.

ты сможешьdatabase_transformer.rbНайдите полный код переноса данных.

После вставки всех данных в таблицу MySQL явной связи между моделями нет, нам также нужно пройтиuuidПодключенная модель преобразуется для использованияidК отношениям между объектами можно получить доступ только напрямую через точечный синтаксис.Установление отношения на самом деле очень просто.Мы получаем все окончания текущего класса как_uuidсвойства, затем выполняет итерацию по всем строкам данных в соответствии сuuidстоимость иpost_uuidЧасть атрибута «post» получает имя таблицы и, наконец, получает соответствующую модель ассоциации.Здесь мы также имеем дело с особыми случаями, такими как полиморфизм:

module RelationBuilder
  def build_relations(class_name, polymorphic_associations = [], rename_associations = {})
    uuids = class_name.attribute_names.select { |name| name.end_with? '_uuid' }

    unless uuids.present?
      STDOUT.puts "#{class_name.to_s.yellow}: skipped"
      STDOUT.puts
      return
    end

    reset_callbacks class_name

    RelationBuilder.profiling do
      models_count = class_name.count
      class_name.unscoped.all.each_with_index do |model, index|
        update_params = uuids.map do |uuid|
          original_association_name = uuid[0...-5]

          association_model = association_model(
            original_association_name,
            model[uuid],
            polymorphic_associations,
            rename_associations
          )

          [original_association_name.to_s, association_model]
        end.compact

        begin
          Hash[update_params].each do |key, value|
            model.send "#{key}=", value
          end
          model.save! validate: false
        rescue Exception => e
          STDERR.puts e
          raise e
        end

        STDOUT.puts "#{index}/#{models_count}\n" if (counter % 1000).zero?
      end
    end
  end
end

После нахождения соответствующей строки данных это очень просто, мы вызываем соответствующуюpost=После обновления внешнего ключа другими методами значение внешнего ключа напрямую сохраняется в базе данных.Как и в процессе переноса данных, мы также будем печатать текущий прогресс во время выполнения этого кода.

в инициализацииRelationBuilder, если мы перейдемconstants, затем вызовRelationBuilder#build!Все отношения в нем будут перестроены, но если его не передать, все подклассы в ActiveRecord будут загружены по умолчанию, а все подклассы в ActiveRecord будут по умолчанию удалены.::модель, которая используется в ActiveRecordhas_and_belongs_to_manyСозданный промежуточный класс мы опишем в следующем разделе, как обрабатывать отношения «многие ко многим» по отдельности:

def initialize(constants = [])
  if constants.present?
    @constants = constants
  else
    Rails.application.eager_load!
    @constants = ActiveRecord::Base.descendants
        .reject { |constant| constant.to_s.include?('::') }
  end
end

Код, связанный с восстановлением отношений, можно найти вrelation_builder.rbНайдите полный код для переноса отношений.

builder = RelationBuilder.new([Post, Comment])
builder.build!

Большинство проблем миграции данных можно решить с помощью двухэтапной миграции данных и восстановления отношений.Однако, поскольку обработка отношений «многие ко многим» в MongoDB и ActiveRecord особенная, нам нужно решать их отдельно.Если все миграции Здесь проблема решена, теперь мы можем использовать следующий файл миграции для переноса базы данных вuuidВсе соответствующие столбцы удаляются:

class RemoveAllUuidColumns < ActiveRecord::Migration[5.1]
  def change
    Rails.application.eager_load!
    ActiveRecord::Base.descendants.map do |klass|
      attrs = klass.attribute_names.select { |n| n.include? 'uuid' }
      next unless attrs.present?
      remove_columns klass.table_name, *attrs
    end
  end
end

На этом весь процесс миграции в основном завершен, а затем возникают другие вопросы, связанные со всем процессом миграции, такие как взаимосвязь между многими парами, важность тестирования и другие темы.

Обработка отношений «многие ко многим»

Отношение «многие ко многим» на самом деле немного сложнее в процессе переноса данных, оно используется в Mongoid.has_and_belongs_to_manyдобавитtag_idsилиpost_idsмножество:

# The post document.
{
  "_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
  "tag_ids" : [
    ObjectId("4d3ed089fb60ab534684b7f2"), 
    ObjectId("4d3ed089fb60ab53468831f1")
  ],
  "title": "xxx",
  "content": "xxx"
}

В ActiveRecord будет создана отдельная таблица, имя которой представляет собой конкатенацию двух имен таблиц в алфавитном порядке.Postа такжеTag, соответствующая таблица «многие ко многим»posts_tags, помимо создания таблицы «многие ко многим»,has_and_belongs_to_manyтакже создаст дваActiveRecord::BaseподклассTag::HABTM_Postsа такжеPost::HABTM_Tags, мы можем просто поэкспериментировать со следующим кодом:

require 'active_record'

class Tag < ActiveRecord::Base; end
class Post < ActiveRecord::Base
  has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
  has_and_belongs_to_many :posts
end
puts ActiveRecord::Base.descendants
# => [Tag, Post, Post::HABTM_Tags, Tag::HABTM_Posts]

Приведенный выше код выводит дваhas_and_belongs_to_manyсгенерированный классTag::HABTM_Postsа такжеPost::HABTM_Tags, у них точно такая же таблицаposts_tags, при работе с отношениями «многие ко многим» нам нужно использовать толькоDatabaseTransformerПосле импорта всех данных в таблицу, затем путем обходаposts_tagsДанные в таблице можно обновить в таблице отношений «многие ко многим»:

class PostsTag < ActiveRecord::Base; end

# migrate data from mongodb to mysql.
transformer = DatabaseTransformer.new 'draven_production'
transformer.import :posts_tags

# establish association between posts and tags.
PostsTag.unscoped.all.each do |model|
  post = Post.find_by_uuid model.post_uuid
  tag = Tag.find_by_uuid model.tag_uuid
  next unless post.present? && tag.present?
  model.update_columns post_id: post.id, tag_id: tag.id
end

все используютhas_and_belongs_to_manyОтношения «многие ко многим» необходимо перенести с помощью приведенного выше кода, на этом шаге необходимо удалить всеuuidполя заполняются раньше.

Важность тестирования

Прежде чем приступить к миграции онлайн-сервисов, нам действительно необходимо выполнить частичное и полное тестирование существующих данных в базе данных.На этапе тестирования мы можем подготовить локальный объем данных, который составляет 1/10 или 1 от объема данных производственной среды. ./100 MongoDB путем локального моделирования среды MongoDB и MySQL перед миграцией, чтобы мы могли найти ошибки в сценарии миграции как можно скорее.

mongodb-pre-migration

Способ подготовки тестовой базы данных заключается в удалении некоторых строк данных основной модели через отношения, которые можно удалить через MongoDB.dependent: :destroyУдалите связанные модели, чтобы максимально обеспечить непротиворечивость и целостность данных, но перед миграцией онлайн-базы данных нам все равно нужно выполнить полный тест миграции для всех данных в MongoDB, чтобы мы могли найти еще несколько скрытых данных. проблема заключается в том, чтобы гарантировать, что меньше ситуаций может произойти, когда он действительно находится в сети.

Миграция базы данных на самом деле является реконструкцией.Перед миграцией базы данных MongoDB мы должны убедиться, что проект имеет полную тестовую систему и тестовые случаи, чтобы мы могли быть уверены, что после проекта не возникнет проблем, которые мы не можем предсказать. реконструируется.Проект управляемый,если тестов мало или вообще нет тестов в проекте,то о рефакторинге не говорите -Модульные тесты — основа рефакторинга.

Суммировать

Миграция с MongoDB на MySQL на самом деле является инженерной проблемой: нам нужно постоянно искать возможные ошибки во всем процессе, разделять относительно сложную задачу и минимизировать влияние миграции на доступность и стабильность сервиса до фактической миграции. секс.

mysql-and-mongodb-work-together

Кроме того, выбор между MongoDB и MySQL не обязательно стоит того или иного.Большую часть данных в проекте мы мигрировали в MySQL, но часть данных для расчета и анализа оставили в MongoDB, чтобы она могла обеспечить выполнение основных задачи проекта не пострадают после того, как MongoDB выйдет из строя, и в то же время скорость резервного копирования и восстановления MySQL будет очень высокой, потому что база данных станет меньше.

И последнее, тестирование действительно важно, без тестирования никто не может этого сделать.Не потерять бизнес-логику в процессе модификации большого количества бизнес-кодов, и даже без тестирования большая часть бизнес-логики могла быть потеряна в день ее разработки.

Если у вас есть какие-либо вопросы по содержанию статьи или вопросы, связанные с миграцией MongoDB, вы можете оставить сообщение в комментариях.Системе комментариев нужна лестница для использования Disqus.

Оригинальная ссылка:Как перейти с MongoDB на MySQL

Follow: Draveness · GitHub

Reference