[RAILS] [Mysql2] Mysql2 :: Fehler: Der angegebene Schlüssel war zu lang, die maximale Schlüssellänge beträgt 767 Byte → Wird durch Erstellen einer neuen Datei mit Zeichenbeschränkungen behoben

Über die Gliederung

Ich habe diesen Fehler in dem Sinne verstanden, dass "Zeichendaten, die in Mysql2 gespeichert werden können, bis zu 767 Bytes betragen! Sie können nicht so wie sie sind auf Mysql migriert werden!".

Aufgrund dieses Fehlers habe ich in diesem Artikel die folgenden zwei Methoden geübt.

Das Wichtigste ist außerdem die Verwendung von MySQL. Es bedeutet, "ob Sie Piktogramme verwenden können oder nicht, wird bei der Definition der Anforderungen entschieden."

Gehen wir ins Detail! !! !!

Über den Fehlerinhalt

Der Fehler "Mysql2 :: Fehler: Angegebener Schlüssel war zu lang; maximale Schlüssellänge beträgt 767 Byte" ist aufgetreten.

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

Über die Situation, in der der Fehler aufgetreten ist

Umgebung#####

--Verwenden von Rails 6.0.0 --Mysql2 wird für die Datenbank verwendet (Anwendung ist Sequel Pro) --Verwenden Sie ein Juwel namens devise (also wurde das Modell mit Rails g devise user erstellt)

Zuerst konnte ich die Situation nicht verstehen und tat mehr von Folgendem:

--Überprüfen Sie mit Schienen db: migrate: status → Es ist ausgefallen

Wie lautet der Zeichencode, bevor Sie zur Lösung gehen? Was sind "utf8" und "utf8mb4"? Was ist Byte?

Ich habe das Konzept nicht verstanden und es wie folgt verstanden.

――Der Zeichencode ist der dem Zeichen zugewiesene Code, z. B. Nr. 1 für "A" und Nr. 2 für "I". (Eigentlich scheint es komplizierter zu sein, wenn man Basisnummern usw. verwendet ...)

―― “utf8” ist der beliebteste Zeichencode der Welt. "Utf8" drückt Zeichen in 1 bis 4 Bytes aus, MySQL kann jedoch nur bis zu 3 Bytes verarbeiten.

Ich zitierte von hier aus

Was ich durch die Kombination der obigen # verstanden habe

Mit anderen Worten, in MySQL

--utf8 ist der Zeichencode, der Zeichen verarbeitet, und utf8bm4 ist der Zeichencode, der Piktogramme verarbeitet.

Die Anzahl der Zeichen, die sein können

Da der Standardwert für Zeichenfolge 255 Zeichen ist

Ich verstehe das.

Wechseln Sie dann zur Fehlerbehebungsmethode

Nachdem die Fehlerursache geklärt wurde, ist es wichtig, sie zu beheben.

Wie ich am Anfang erwähnte,

Zuerst habe ich es mit der obigen Methode gelöst! !! !! (Vielen Dank)

Wenn Sie einen Überblick über die Lösung geben,

【Problem】 "4 Bytes ❌ 255 Zeichen = 1020 Bytes" (utf8bm4): point_right_tone3: Es überschreitet 767 Bytes, die von MySQL gespeichert werden können! !! : point_right_tone3: Dieses Mal bin ich in diesem Zustand und es ist ein Fehler

[Darüber nachdenken] Dann setzen wir die Obergrenze der Anzahl der Zeichen auf 191 Zeichen, damit sie 767 Bytes nicht überschreitet ("4 Bytes ❌ 191 Zeichen = 764 Bytes")! Es ist eine Methode. (Verwendung von utf8bm4, damit Piktogramme verwendet werden können)

Erstellen Sie eine neue mysql.rb wie unten unter config / initializer gezeigt. (Einschließlich des folgenden Codes stammt er aus dem Artikel von @ 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

Nach Eingabe der obigen Datei

【Terminal】
rails db:migrate

Als ich das tat, wurde es erfolgreich migriert! !! !! (Als ich mir Sequel Pro ansah, MySQL, gab es eine Spalte.)

Von dort aus, was ich als # angesehen habe

Nun, ich habe es sicher gelöst, aber ich dachte, ich könnte mir die folgende Art vorstellen, über die Methode nachzudenken, die 767 Bytes für das Problem nicht überschreitet.

【Problem】 "4 Bytes ❌ 255 Zeichen = 1020 Bytes" (utf8bm4): point_right_tone3: Es überschreitet 767 Bytes, die von MySQL gespeichert werden können! !! : point_right_tone3: Dieses Mal bin ich in diesem Zustand und es ist ein Fehler

[Darüber nachdenken] Wenn Sie in der Anwendung keine Piktogramme verwenden, ändern Sie diese in "3 Bytes ❌ 255 Zeichen = 765 Bytes" (utf8). Mit anderen Worten, anstatt eine Datei mit 191 Zeichen oder weniger zu erstellen, sollte der in "config> database.yml" beschriebene Zeichencode von "utf8bm4" in "utf8" umgeschrieben und migriert werden! ??

Ich dachte.

Ich werde es von hier aus üben, aber aus der Schlussfolgerung habe ich gelernt, dass "es aus dem Modell neu erstellt wird (es reicht nicht aus, die Migration neu zu schreiben)". (Das heißt, es ist mühsam und schwierig.)

"Ich kann die Migration nicht umschreiben" bedeutet, dass eine mysteriöse Migrationsdatei (nicht angewiesen) mit "Rails db: migrate" angezeigt wird und diese Migrationsdatei nicht erforderlich ist. Ändern Sie sie daher in eine fiktive Datei und löschen Sie sie oder setzen Sie sie zurück. Aber selbst wenn ich versuche, es zu löschen, verschwindet es nicht.

Ich habe das Modell mit "Rails d Devise User" gelöscht und mit "Rails G Devise User" neu erstellt. Schließlich habe ich eine Anwendung mit dem Zeichencode "utf8" ohne Fehler erhalten.

Jetzt übe! (Ich übe die obige Überlegung aus der Situation heraus, in der der Fehler früher behoben wurde.)

① Einmal zurückrollen
〇〇@〇〇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) =======================
② Überprüfen Sie den Migrationsstatus (es ist inaktiv, also in Ordnung!)
〇〇@〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

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

③ Migration ausführen (OK, da der Fehler reproduziert werden konnte!)
〇〇@〇〇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)
④ Schreiben Sie config> database.yml in utf8 ###### um
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock
⑤ Schienen ausführen db: reset (gutes Gefühl!)
〇〇@〇〇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.
⑥ Schienen ausführen db: migrieren (fühlt sich gut an!)
〇〇@〇〇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? Was ist eine 000-Datei?)
〇〇@〇〇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
⑦ Da es zu "** NO FILE *" geworden ist, werden 000 Dateien nicht gelöscht, selbst wenn ich die Migration in eine fiktive Datei (Beispiel) ändere und sie zurücksetze
〇〇@〇〇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
⑦ Setzen Sie den Status zurück und überprüfen Sie ihn, aber 000 Dateien werden nicht gelöscht.
〇〇@〇〇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

⑧ Löschen Sie das Modell
〇〇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
⑨ Erstellen Sie das Modell ###### neu
〇〇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
⑩ Migration durchführen
〇〇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 Überprüfen Sie den Status (endlich fertig !!!!!!)
〇〇noMacBook-Air devise_app % rails db:migrate:status 

database: devise_app_development

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

das ist alles.

Am Ende

Ich habe versucht, die Überlegung zu üben, Es stellt sich heraus, dass Sie zum Ändern der Informationen in database.yml das Modell neu gestalten müssen, anstatt einen Rollbeutel zu verwenden.

Dieses Mal habe ich nicht viel über das Modell geschrieben, also hat es mich nicht betroffen, Wenn hiermit die Tabelle, Spalte, der Datensatz, die Migration usw. einschließlich des Modells neu erstellt werden sollen, ist dies problematisch und schwierig.

Ich habe gelernt, dass es wichtig ist, die Anforderungen für die Bearbeitung von database.yml, einschließlich utf8, zu definieren (bevor Sie am Anfang "Rails db: create" ausführen) und diese dann festzulegen.

Danach habe ich eine Methode in Betracht gezogen, die diesmal "767 Bytes" nicht überschreitet, aber der Artikel von @ terufumi1122 sagte auch, dass sie "767 Bytes" überschreiten darf.

Um den Fehler zu beheben, wurde mir erneut klar, dass es notwendig ist, die Anwendung je nach Zweck aus verschiedenen Richtungen flexibel zu betrachten, und dass der Standpunkt "WARUM" wichtig ist, um die Anzahl der Abhebungen zu erhöhen.

Danke fürs Zuschauen. Wenn Sie die Ursache der Mystery-Datei kennen oder etwas falsch gepostet haben, lassen Sie es mich bitte wissen.

Recommended Posts

[Mysql2] Mysql2 :: Fehler: Der angegebene Schlüssel war zu lang, die maximale Schlüssellänge beträgt 767 Byte → Wird durch Erstellen einer neuen Datei mit Zeichenbeschränkungen behoben
[Fehler] Mysql2 :: Fehler: Der angegebene Schlüssel war zu lang, die maximale Schlüssellänge beträgt 767 Byte