【问题标题】:How to deploy MySQL database from v5.7.19 to a remote MySQL database of v5.5.6如何将 MySQL 数据库从 v5.7.19 部署到远程 MySQL 数据库 v5.5.6
【发布时间】:2020-01-17 16:16:29
【问题描述】:

其实是我的错,我之前没有想到,我的远程服务器 MySQL 版本(在共享主机上)是5.5.6,但我的本地 MySQL 版本是5.7.19

我开发了一个 Laravel (v6.6.0) Web 应用程序,我在第一次运行时就在其中运行了迁移,但由于它完全是一个个人项目,我继续在必要的地方和方式修改数据库,(但关闭-记录,我也一直在更改迁移文件,尽管在第一次实例之后我从未运行过它们)。

我从其他一些表中迁移了所有数据,并且我的应用程序已准备好部署。但是当我导出本地数据库表并将它们导入远程数据库时,它给了我一个众所周知的错误:

指定的密钥太长;最大密钥长度为 767 字节

我实际上忽略了它,因为所有表格都很好地导入了。但最近我发现了它的警告 - 我的远程数据库中不存在所有 AUTO_INCREAMENTPRIMARY_KEY

searched 我能做到,但所有解决方案都建议删除数据库并使用 UTF-8 重新创建它,但实际上这不是我的情况。像下面的 PHP 方式这样的解决方案也不是我的情况,因为我在收到错误时使用 PHPMyAdmin 导入我的表:

// File: app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Schema;

public function boot() 
{
    Schema::defaultStringLength(191); 
}

我还尝试在我的目标数据库上运行以下命令:

SET @global.innodb_large_prefix = 1;

但没有运气。我还尝试替换所有出现的 .sql 本地文件:

  • utf8mb4utf8,以及
  • utf8mb4_unicode_ciutf8_general_ci

但又没有运气了。

具体从哪里来的错误,实际上是更长的外键,比如xy_section_books_price_unit_id_foreign,而在这个阶段,当一切都完成后,我不知道我该如何重构所有的与5.5 兼容的外键。

谁能解释一下我的问题?

如何在不丢失PRIMARY_KEYs、外键和INDEXes 到v5.5 MySQL 数据库的情况下部署我的本地数据库 (v5.7) 以保持数据完整?

【问题讨论】:

    标签: php mysql laravel-6


    【解决方案1】:

    更改您的键名。您可以在创建它们时覆盖“默认生成的”非常长的键名。 请参阅 https://laravel.com/docs/5.8/migrations 文档的可用索引类型

    从 SQL Server 迁移到 MySQL 时,我遇到了类似的问题,并且自动生成的具有完整长命名空间的键名和键名太长了。因此,通过用手工制作的唯一索引名称替换所有这些,我解决了这些问题。

    在 MySQL 中你并不需要唯一的名称,但如果你使用 SQLITE 进行单元测试,你确实需要唯一的名称。

    所以而不是:

    public function up() 
    {
       ....
       $table->primary('id');
      // generates something like work_mayeenul_islam_workhorse_models_model_name_id_primary_key
       $table->index(['foobar','bazbal']);
       // generates something like work_mayeenul_islam_workhorse_models_model_name_foobar_bazbal_index
    }
    

    您使用自己定义的,您知道这些是短索引名称。

    public function up() 
    {
       ....
       $table->primary('id', 'PK_short_namespace_modelname_id');
       $table->index(['foobar', 'bazbal'], 'IX_short_namespace_modelname_foobar_bazbal');
    }
    

    【讨论】:

    • 感谢您的回答。但实际上我被外键困住了,除了索引,我想我没有任何清晰的方法,对吗?
    • 通过外键,您还可以定义自己的索引名称。阅读我在答案中发布的链接。只需确保它是唯一的并且在限制范围内。
    【解决方案2】:

    感谢@Tschallacka 的回答。我的问题是,我不能再运行php artisan migrate,因为我在这些表上有实时数据。首先,这个问题让我学到了新的东西(感谢我的同事 Nazmul Hasan):

    经验教训

    密钥是独一无二的,但甚至可能是乱码

    首先,我在外键中发现了一个模式:{table_name}_{column_name}_foreign。同样在索引键中:{table_name}_{column_name}_index。吸取的教训是,外键或索引键不必采用这种格式才能起作用。它必须是独一无二的,但它可以是任何东西,也可以是乱码。所以password_resets_email_index 键可以很容易地是pre_idx 或其他任何东西。

    但这不是问题。

    解决方案

    对于解决方案,我尝试逐个表和逐个范围挖掘.sql 文件表。我发现只有 2 个 UNIQUE 键声明显示阻塞错误。还有其他 3 次出现警告的情况:

    ALTER TABLE `contents` ADD KEY `contents_slug_index` (`slug`); --- throwing warning
    ALTER TABLE `foo_bar` ADD UNIQUE KEY `slug` (`slug`); --- throwing error
    ALTER TABLE `foo_bar` ADD KEY `the_title_index` (`title`) USING BTREE; --- throwing warning
    ALTER TABLE `password_resets` ADD KEY `password_resets_email_index` (`email`); --- throwing waring
    ALTER TABLE `users` ADD UNIQUE KEY `users_email_unique` (`email`); --- throwing error
    

    最后,解决方案来自this particular StackOverflow thread

    • INNODB utf8 VARCHAR(255)
    • INNODB utf8mb4 VARCHAR(191)

    在了解该 SO 线程的情况下检查这些表后,我发现:

    • 问题是:在 MySQL 5.5/5.6 中使用排序规则 utf8mb4_unicode_ci,字段值不能大于 191。但是,
    • 在 MySQL 5.5/5.6 中使用排序规则 utf8_unicode_ci,字段值不能大于 255。但utf8_unicode_ci 无法保存表情符号等。

    所以我决定留在utf8_unicode_ci 以获得相对较长的价值。所以对于临时补救措施

    • 我更改了所有这些特定的列,从utf8mb4_unicode_ci 更改为utf8_unicode_ci
    • 如果这些特定列超过 255,我将它们减少到 255

    例如,如果表格如下:

    CREATE TABLE `foo_bar` (
      `id` bigint(20) UNSIGNED NOT NULL,
      `cover` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
      `title` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL,
      `slug` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    

    我只更改了必要的列:

    CREATE TABLE `foo_bar` (
      `id` bigint(20) UNSIGNED NOT NULL,
      `cover` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
      `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    

    就是这样。这种临时补救措施效果很好,我不必更改外键或索引键。

    为什么要采取这种临时补救措施?因为最终我会使用 MySQL 5.7+,但在此之前,至少要尝试应对以前的版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 2013-02-17
      • 2014-05-01
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多