Rails5: Почему миграция нарушает мою производственную среду, но не мою тестовую среду? - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть миграция в рельсах, которая выполняет следующие действия:

class AddMissingIndexes < ActiveRecord::Migration[5.1]
  def change
    # Applications
    add_index :applications, :evid, length: { evid: 255 }
  end
end

Это, кажется, проходит гладко в моей тестовой среде

Однако, когда я запускаю миграциюв моей рабочей среде я получаю эту ошибку:

Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE  INDEX `index_applications_on_evid`  ON `applications` (`evid`(255)) 

Я пытаюсь решить эту проблему, используя второй ответ из этого вопроса

class AddMissingIndexes < ActiveRecord::Migration[5.1]
  def change
    # Applications
    add_index "applications", ["evid"], :name => :evid, :length => { :evid => 255 }
  end
end

Однако я хочу убедиться, что это работает, прежде чем вносить какие-либо дальнейшие изменения в схему.Поэтому мне нужно иметь возможность воспроизвести эту ошибку в моей тестовой среде.

Тестовая среда:

+-------------------------+------------------+
| Variable_name           | Value            |
+-------------------------+------------------+
| innodb_version          | 5.5.62           |
| protocol_version        | 10               |
| slave_type_conversions  |                  |
| version                 | 5.5.62-0+deb8u1  |
| version_comment         | (Debian)         |
| version_compile_machine | x86_64           |
| version_compile_os      | debian-linux-gnu |
+-------------------------+------------------+

Производственная среда

+-------------------------+---------------------+
| Variable_name           | Value               |
+-------------------------+---------------------+
| innodb_version          | 5.6.40              |
| protocol_version        | 10                  |
| slave_type_conversions  |                     |
| version                 | 5.6.40-log          |
| version_comment         | Source distribution |
| version_compile_machine | x86_64              |
| version_compile_os      | Linux               |
+-------------------------+---------------------+

Использование SHOW GLOBAL VARIABLES LIKE 'innodb_%'; Я могу видеть свою базу данных тестовой среды, и вот что я обнаружил, что моя локальная среда БД имеет следующие переменные, подобные этой:

Тестовая среда

innodb_file_format=Barracuda;
innodb_large_prefix=1;
innodb_file_per_table=1;
innodb_file_format_max=Barracuda;
innodb_strict_mode=1;
character_set_server='utf8mb4';

Производственная среда

innodb_file_format=Antelope;
innodb_large_prefix=OFF;
innodb_file_per_table=ON;
innodb_file_format_max=Antelope;
innodb_strict_mode=OFF;
character_set_server='utf8mb4';

Я попытался воспроизвести свою производственную среду, задавая переменные, равные 1 за раз.Но безрезультатно.

1 Ответ

0 голосов
/ 26 февраля 2019

Запустите SHOW CREATE TABLE applications\G как в своей тестовой, так и в производственной среде.Я предсказываю, что разница будет:

Тест:

CREATE TABLE `applications` (
  ...
  `evid` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Производство:

CREATE TABLE `applications` (
  ...
  `evid` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

Индекс должен умещаться в 767 байтов, как говорит ошибка,Набор символов utf8 подсчитывает 3 байта на символ к этому пределу, поэтому 3 * 255 = 765, что соответствует.

Тогда как utf8mb4 считает 4 байта на символ.4 * 255 = 1020, что слишком долго.

Вы можете индексировать VARCHAR (191), когда используете utf8mb4, чтобы оставаться в пределах 767 байт.

В качестве альтернативы, вы можете использовать более новый формат строки InnoDB для поддержки размера индекса до 3072 байт.См. mysql change innodb_large_prefix

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


Re ваш обновленный вопрос с переменными конфигурации innodb.

Я вижу, что ваша производственная среда имеет настройки, которые означают, что она не можетдля определения таблиц с форматом файла Barracuda, что означает отсутствие формата строки DYNAMIC, что означает отсутствие innodb_large_prefix.

Вам необходимо настроить параметры в соответствии с вашей тестовой средой, а затем вам, вероятно, потребуется перестроить таблицу так,он действительно в формате Barracuda с форматом строк DYNAMIC.

Я также рекомендую (еще раз) обновить тестовый сервер до той же версии MySQL, которую вы используете в рабочей среде.

Также сравните другие параметры конфигурации, чтобы увидеть, есть ли другие различия (кроме тех, которые подходят для отличия от производственной, например, innodb_buffer_pool_size).

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

...