[RAILS] [Mysql2] Mysql2 :: Erreur: La clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets → Résolu en créant un nouveau fichier avec des restrictions de caractères

À propos du plan

J'ai compris cette erreur dans le sens que "les données de caractères qui peuvent être stockées dans Mysql2 font jusqu'à 767 octets! Elles ne peuvent pas être migrées vers Mysql telles quelles!".

Sur la base de cette erreur, dans cet article, j'ai pratiqué les deux méthodes suivantes.

La chose la plus importante en plus est l'utilisation de MySQL. Cela signifie "si vous pouvez ou non utiliser des pictogrammes est décidé lors de la définition des exigences."

Entrons dans les détails! !! !!

À propos du contenu de l'erreur

L'erreur «Mysql2 :: Error: la clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets» s'est produite.

【Terminal】

〇〇@〇〇noMacBook-Air devise_app % rails db:migrate:reset                          
Dropped database 'devise_app_development'
Dropped database 'devise_app_test'
Created database 'devise_app_development'
Created database 'devise_app_test'
== 20200925212154 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0174s
-- add_index(:users, :email, {:unique=>true})
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Specified key was too long; max key length is 767 bytes
/Users/〇〇/projects/devise_app/db/migrate/20200925212154_devise_create_users.rb:39:in `change'
/Users/〇〇/projects/devise_app/bin/rails:9:in `<top (required)>'
/Users/〇〇/projects/devise_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'

Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes
/Users/〇〇/projects/devise_app/db/migrate/20200925212154_devise_create_users.rb:39:in `change'
/Users/〇〇/projects/devise_app/bin/rails:9:in `<top (required)>'
/Users/〇〇/projects/devise_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'

Caused by:
Mysql2::Error: Specified key was too long; max key length is 767 bytes
/Users/〇〇/projects/devise_app/db/migrate/20200925212154_devise_create_users.rb:39:in `change'
/Users/〇〇/projects/devise_app/bin/rails:9:in `<top (required)>'
/Users/〇〇/projects/devise_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:migrate:reset => db:migrate
(See full trace by running task with --trace)

À propos de la situation dans laquelle l'erreur s'est produite

environnement#####

--Utilisation de Rails 6.0.0 --Mysql2 est utilisé pour la base de données (l'application est Sequel Pro) --Utilisez une gemme appelée devise (le modèle a donc été créé avec des rails g devise user) --Dans la conception, j'essayais de créer une colonne de type string (exemple: t.string: email) dans le fichier de migration. --Lorsque j'ai créé un fichier de migration et exécuté rails db: migrate, une erreur s'est produite.

Au début, je ne pouvais pas comprendre la situation et j'ai fait plusieurs des choses suivantes:

--Vérifier avec les rails db: migrer: état → Il est en panne

Avant de passer à la solution, quel est le code de caractère en premier lieu? Que sont "utf8" et "utf8mb4"? Qu'est-ce que l'octet?

Je n'ai pas compris le concept et je l'ai compris comme suit.

――Le code de caractère est le code attribué au caractère, tel que le n ° 1 pour "A" et le n ° 2 pour "I". (En fait, cela semble être plus compliqué en utilisant des nombres de base, etc.)

―― «utf8» est le code de caractère le plus populaire au monde. "Utf8" exprime des caractères de 1 à 4 octets, mais MySQL ne peut gérer que 3 octets.

J'ai cité d'ici

Ce que j'ai compris en combinant les

En d'autres termes, dans MySQL

--utf8 est le code de caractère qui gère les caractères, et utf8bm4 est le code de caractère qui gère les pictogrammes.

Le nombre de caractères pouvant être

La valeur par défaut de la chaîne étant de 255 caractères

Je comprends que.

Ensuite, allez à la résolution d'erreur

Maintenant que la cause de l'erreur a été élucidée, il est important de la résoudre.

Comme je l'ai mentionné au début,

Tout d'abord, je l'ai résolu par la méthode ci-dessus! !! !! (Merci)

Si vous donnez un aperçu de la solution,

【problème】 "4 octets ❌ 255 caractères = 1020 octets" (utf8bm4): point_right_tone3: Il dépasse 767 octets qui peuvent être sauvés par MySQL! !! : point_right_tone3: Cette fois je suis dans cet état et c'est une erreur

[Y penser] Ensuite, fixons la limite supérieure du nombre de caractères à 191 caractères pour qu'elle ne dépasse pas 767 octets ("4 octets ❌ 191 caractères = 764 octets")! C'est une méthode. (Comment utiliser utf8bm4 tel quel pour que les pictogrammes puissent être utilisés)

Créez un nouveau mysql.rb comme indiqué ci-dessous sous config / initializer. (Y compris le code ci-dessous, il est tiré de l'article de @ terufumi1122.)

config/initializer/mysql.rb
require 'active_record/connection_adapters/abstract_mysql_adapter'

module ActiveRecord
  module ConnectionAdapters
    class AbstractMysqlAdapter
      NATIVE_DATABASE_TYPES[:string] = { :name => "varchar", :limit => 191 }
    end
  end
end

Après avoir entré le fichier ci-dessus

【Terminal】
rails db:migrate

Quand je l'ai fait, il a été migré avec succès! !! !! (Quand j'ai regardé Sequel Pro, qui est MySQL, il y avait une colonne.)

À partir de là, ce que j'ai considéré

Eh bien, je l'ai résolu en toute sécurité, mais j'ai pensé que je pourrais penser à la façon suivante de penser à la méthode qui ne dépasse pas 767 octets pour le problème.

【problème】 "4 octets ❌ 255 caractères = 1020 octets" (utf8bm4): point_right_tone3: Il dépasse 767 octets qui peuvent être sauvés par MySQL! !! : point_right_tone3: Cette fois je suis dans cet état et c'est une erreur

[Y penser] Ensuite, si vous n'utilisez pas de pictogrammes dans l'application, pourquoi ne pas le changer en "3 octets ❌ 255 caractères = 765 octets" (utf8)? En d'autres termes, au lieu de créer un fichier avec 191 caractères ou moins, le code de caractère décrit dans "config> database.yml" devrait être réécrit de "utf8bm4" à "utf8" et migré! ??

J'ai pensé.

Je vais pratiquer à partir d'ici, mais de la conclusion, j'ai appris que "il sera recréé à partir du modèle (il ne suffit pas de réécrire la migration)". (Autrement dit, c'est gênant et difficile.)

«Je ne peux pas réécrire la migration» signifie qu’un mystérieux fichier de migration (sans instruction) apparaît avec «rails db: migrate», et que ce fichier de migration n’est pas nécessaire, alors changez-le en fichier fictif et supprimez-le ou réinitialisez-le. Mais même si j'essaye de l'effacer, ça ne disparaît pas.

J'ai effacé le modèle avec "rails d conception user" et je l'ai recréé avec "rails g devise user", et j'ai finalement obtenu une application avec le code de caractère "utf8" sans aucune erreur.

Maintenant, pratiquez! (Je pratique la considération ci-dessus à partir de la situation où l'erreur a été résolue plus tôt)

① Reculer une fois
〇〇@〇〇noMacBook-Air devise_app % rails db:rollback       
== 20200925212154 DeviseCreateUsers: reverting ================================
-- remove_index(:users, {:column=>:reset_password_token})
   -> 0.0099s
-- remove_index(:users, {:column=>:email})
   -> 0.0074s
-- drop_table(:users)
   -> 0.0040s
== 20200925212154 DeviseCreateUsers: reverted (0.0250s) =======================
② Vérifiez l'état de la migration (il est en panne, donc ça va!)
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
  down    20200925212154  Devise create users

③ Exécutez la migration (OK car l'erreur pourrait être reproduite!)
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate        
== 20200925212154 DeviseCreateUsers: migrating ================================
-- create_table(:users)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Table 'users' already exists
/Users/〇〇/projects/devise_app/db/migrate/20200925212154_devise_create_users.rb:5:in `change'
/Users/〇〇/projects/devise_app/bin/rails:9:in `<top (required)>'
/Users/〇〇/projects/devise_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'

Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'users' already exists
/Users/〇〇/projects/devise_app/db/migrate/20200925212154_devise_create_users.rb:5:in `change'
/Users/〇〇/projects/devise_app/bin/rails:9:in `<top (required)>'
/Users/〇〇/projects/devise_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'

Caused by:
Mysql2::Error: Table 'users' already exists
/Users/〇〇/projects/devise_app/db/migrate/20200925212154_devise_create_users.rb:5:in `change'
/Users/〇〇/projects/devise_app/bin/rails:9:in `<top (required)>'
/Users/〇〇/projects/devise_app/bin/spring:15:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
④ Réécrire config> database.yml en utf8
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock
⑤ Exécuter les rails db: réinitialiser (bonne sensation!)
〇〇@〇〇noMacBook-Air devise_app % rails db:reset  
Dropped database 'devise_app_development'
Dropped database 'devise_app_test'
Created database 'devise_app_development'
Created database 'devise_app_test'
You have 1 pending migration:
  20200925212154 DeviseCreateUsers
Run `rails db:migrate` to update your database then try again.
⑥ Exécuter les rails db: migrer (ça fait du bien!)
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate
== 20200925212154 DeviseCreateUsers: migrarails db:migrateting ================================
-- create_table(:users)
   -> 0.0109s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0087s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0085s
== 20200925212154 DeviseCreateUsers: migrated (0.0283s) =======================
⑥ rails db: migrate: status (Oh? Qu'est-ce qu'un fichier 000?)
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     000             ********** NO FILE **********
   up     20200925212154  Devise create users
⑦ Puisqu'il est devenu "** NO FILE *", même si je modifie la migration vers un fichier fictif (Sample) et que je l'annule, 000 fichiers ne descendent pas
〇〇@〇〇noMacBook-Air devise_app % rails db:rollback STEP=2
〇〇@〇〇noMacBook-Air devise_app % 
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     000             Sample
  down    20200925212154  Devise create users
⑦ Réinitialisez et vérifiez l'état, mais 000 fichiers ne descendent pas
〇〇@〇〇noMacBook-Air devise_app % rails db:reset          
Dropped database 'devise_app_development'
Dropped database 'devise_app_test'
Created database 'devise_app_development'
Created database 'devise_app_test'
You have 1 pending migration:
  20200925212154 DeviseCreateUsers
Run `rails db:migrate` to update your database then try again.
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     000             ********** NO FILE **********
  down    20200925212154  Devise create users

⑧ Supprimer le modèle
〇〇noMacBook-Air devise_app % rails d devise user   
Running via Spring preloader in process 10337
      invoke  active_record
      remove    db/migrate/20200925212154_devise_create_users.rb
      remove    app/models/user.rb
      invoke    test_unit
      remove      test/models/user_test.rb
      remove      test/fixtures/users.yml
       route  devise_for :users
⑨ Refaites le modèle
〇〇noMacBook-Air devise_app % rails g devise user    
Running via Spring preloader in process 10485
      invoke  active_record
      create    db/migrate/20200926073222_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users
⑩ Effectuer la migration
〇〇noMacBook-Air devise_app % rails db:migrate        
== 20200926073222 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0275s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0434s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0108s
== 20200926073222 DeviseCreateUsers: migrated (0.0821s) =======================
11 Vérifiez l'état (enfin terminé !!!!!!)
〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200926073222  Devise create users

c'est tout.

À la fin

J'ai essayé de pratiquer la considération, Il s'avère que pour modifier les informations dans database.yml, vous devez remodeler le modèle au lieu d'utiliser un sac en rouleau.

Cette fois, je n'ai pas beaucoup écrit sur le modèle, donc ça ne m'a pas affecté, S'il s'agit de recréer la table, la colonne, l'enregistrement, la migration, etc. y compris le modèle, ce sera gênant et difficile.

J'ai appris qu'il est important de définir les exigences pour l'édition de database.yml, y compris utf8 (avant de faire "rails db: create" au début), puis de le définir.

Après cela, j'ai envisagé une méthode qui ne dépasse pas "767 octets" cette fois, mais l'article de @ terufumi1122 dit aussi qu'il est permis de dépasser "767 octets".

Afin de résoudre l'erreur, j'estime qu'il est nécessaire d'examiner la demande de manière flexible dans diverses directions selon le but, et que le point de vue «POURQUOI» est important pour augmenter le nombre de retraits.

Merci d'avoir regardé. Si vous connaissez la cause du fichier mystère ou si vous avez publié quelque chose de mal, veuillez me le faire savoir.

Recommended Posts

[Mysql2] Mysql2 :: Erreur: La clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets → Résolu en créant un nouveau fichier avec des restrictions de caractères
[Erreur] Mysql2 :: Erreur: la clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets