Rails5:为什么迁移会破坏我的生产环境而不是我的测试环境?

问题描述 投票:1回答:1

我在rails中进行了迁移,执行以下操作:

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)) 

我正在尝试使用this question的第二个答案解决这个问题

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。但无济于事。

mysql migration ruby-on-rails-5
1个回答
1
投票

在测试和生产环境中运行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,这太长了。

使用utf8mb4时,可以索引VARCHAR(191),以保持在767字节内。

或者,您可以使用较新的InnoDB行格式来支持最大3072字节的索引大小。见mysql change innodb_large_prefix

如果您想避免这些意外,在测试和生产中运行相同版本的MySQL非常重要,并确保尽可能接近MySQL配置选项,并确保表定义相同。


使用innodb配置变量重新更新您的问题。

我看到你的生产环境有一些设置意味着它无法用Barracuda文件格式定义表,这意味着没有DYNAMIC行格式,这意味着没有innodb_large_prefix

您需要使设置与您的测试环境相匹配,然后您可能需要重建您的表,因此它实际上采用带有DYNAMIC行格式的Barracuda格式。

我还建议(再次)将测试服务器升级到您在生产中运行的相同MySQL版本。

还要比较其他配置设置,看看是否还有其他差异(除了适合与生产不同的那些,比如innodb_buffer_pool_size)。

您还应该确保使用技术堆栈的其他部分的相同版本,如Linux版本,Ruby版本等。如果您对版本不兼容性感到惊讶,那么这是项目不稳定和计划延迟的众所周知的来源,如果您未能使您的开发和测试环境与您的生产环境相匹配。

© www.soinside.com 2019 - 2024. All rights reserved.