【问题标题】:Rails5: Why is a migration breaking my production environment but not my test environment?Rails5:为什么迁移会破坏我的生产环境,但不会破坏我的测试环境?
【发布时间】:2019-02-26 18:28:15
【问题描述】:

我在 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】:

在您的测试和生产环境中运行 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 配置变量更新您的问题。

我看到您的生产环境的设置意味着它无法使用梭子鱼文件格式定义表,这意味着没有 DYNAMIC 行格式,这意味着没有innodb_large_prefix

您需要使设置与您的测试环境相匹配,然后您可能需要重建您的表格,使其真正采用梭子鱼格式和 DYNAMIC 行格式。

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

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

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

【讨论】:

  • 我在我的测试环境中运行该命令并得到以下结果:'evid' varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL ... ) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC
  • SELECT @@innodb_large_prefix; 怎么样?并在生产中进行相同的调查以进行比较。
  • 在测试中添加执行最后一个命令给了我一个普通的旧 0 这是我在生产中运行 SHOW CREATE TABLE applications\G 时的生产外观'evid' varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC |
  • innodb_large_prefix 必须为 1(或 ON)以允许较大的索引大小。阅读:dev.mysql.com/doc/refman/5.6/en/… 但我不知道为什么它在测试环境中有效,而在其他环境中无效。
  • 有没有办法显示当前在我的测试环境中是如何设置的?类似SHOW GLOBAL innodb_file_format
猜你喜欢
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 2013-06-07
  • 1970-01-01
相关资源
最近更新 更多