Как исправить MySql: размер столбца индекса слишком велик (миграция Laravel)

Я продублировал проект с бродячей коробкой, которая устанавливает Debian, Nginx, PhpMyAdmin, .. С новым проектом Laravel's php artisan migrate больше не работает, и я получаю ошибку:

[Illuminate\Database\QueryException]                                                                                                                                      
  SQLSTATE[HY000]: General error: 1709 Index column size too large. The maximum column size is 767 bytes. (SQL: alter table `courses` add unique `courses_name_unique`(`na  
  me`))

Когда я делаю дамп (структура + данные) из рабочей базы данных проекта и импортирую ее в базу данных с ошибками при переносе, все в порядке, и создаются все таблицы, а данные импортируются.

Как я могу исправить размер, чтобы я мог запустить метод переноса?

6 ответов

Решение

Как вы можете видеть в сообщении об ошибке - "Максимальный размер столбца составляет 767 байт", если вы хотите создать индекс для него. VARCHAR(255) столбец может занимать до 765 (255*3) байтов, используя utf8 и 1020 (255*4) байтов с использованием utf8mb4, Это потому что в MySQL utf8 занимает до 3 байтов и utf8mb4 до 4 байтов (реальный UTF8). Таким образом, создавая VARCHAR(255) (уникальный) индекс с utf8mb4 не удастся.

Это ваши варианты решения проблемы:

Установить параметры сортировки по умолчанию в my.ini:

collation_server=utf8_unicode_ci
character_set_server=utf8

Установите параметры сортировки по умолчанию для базы данных при создании:

CREATE DATABASE IF NOT EXISTS `your_db` COLLATE 'utf8_unicode_ci'

Установите параметры сортировки по умолчанию для таблицы / столбца. (Я не рекомендую это)

Измените размер столбца на 190 (varchar(190)) или менее.

Laravel 5.4 fix

Конфигурация сервера Mysql перезаписывается командой миграции Laravel. Он установит параметры сортировки и кодировки в версию конфигурации.

Изменить поля charset а также collation движка БД в конфигурационном файле базы данных, расположенном в config/database.php,

..
'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            //'charset' => 'utf8mb4',
            //'collation' => 'utf8mb4_unicode_ci',
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],
..

Для Мариадб, обновите свой *my.cnf файл со следующей конфигурацией,

innodb_default_row_format=dynamic
innodb_file_format=barracuda
innodb_file_per_table=true
innodb_large_prefix=true

Затем вы должны перезагрузить mariadb сервис для обновления конфигурации для вступления в силу.

Три решения, каждое с недостатком:

  • MySQL 5.7 позволяет избежать этой проблемы. Подумайте об обновлении.

  • VARCHAR(255) обычно это больше, чем необходимо. Если вы можете безопасно сжаться до 191 или меньше, ошибка исчезнет.

  • Переключитесь на utf8 (с utf8mb4), если вам не нужны китайский или эмодзи.

Для Laravel 5.5 или выше измените в файле config/database.php движок на InnoDB ROW_FORMAT=DYNAMIC:

'connections' => [
    ...
    'mysql' => [
        ...
        'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',
 ]]

Благодаря ларакастам: https://laracasts.com/discuss/channels/eloquent/migrations-and-table-options-row-format

В App\Providers\AppServiceProvider.php импортируйте Schema

use Illuminate\Support\Facades\Schema;

и в boot() функция добавить эту строку:

Schema::defaultStringLength(191);

По умолчанию MySQL использует набор символов utf8, что означает, что мы используем 3 байта на каждый 1 символ. Это означает, что тип столбца varchar(10) использует 30 байтов, в результате чего максимальный размер префикса для компактного формата строки будет эквивалентен varchar(255). Это 255 * 3 байта = 765 байтов, что на два байта меньше максимального значения в 767 байтов.

Если для innodb_large_prefix задано значение on и используется формат строки COMPRESSED или DYNAMIC, вы можете увеличить максимальный размер префикса до 65536 байт вместо 767 байт. На приведенной ниже диаграмме показана максимальная длина символа с большим префиксом InnoDB и [COMPRESSED| DYNAMIC] форматы строк. Эти значения, ожидаемые для utf8mb4, превышают максимальный размер строки таблицы, поэтому нет возможности выйти за эти пределы

Более подробная информация здесь https://discuss.pivotal.io/hc/en-us/articles/115004086747-Apps-are-down-due-to-the-Maximum-Column-Size-is-767-bytes-Constraint-in-MySQL

Также была эта проблема, что я только что сделал, был возвращен из utf8mb4_unicode_ci в utf8_unicode_ci в сценарии подключения БД

Работает с 5.5.52-MariaDB.

Установить всю кодировку на utf8_general_ci (сервер, база данных, соединение).

Другие вопросы по тегам