NO_ENGINE_SUBSTITUTIONが無効になっていて、INNODBがアクティブではない、悪い組み合わせ
- MySql 5.5までは、sqlmodeのデフォルトは空白の文字列でした。つまり、sqlmodeNO_ENGINE_SUBSTITUTIONはデフォルトで設定されていませんでした。
MySqlのドキュメント(https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_no_engine_substitutionを参照)によると、これはsqlmodeNO_ENGINE_SUBSTITUTIONの意味です。
CREATETABLEやALTERTABLEなどのステートメントで、で無効になっている、またはコンパイルされていないストレージエンジンが指定されている場合は、デフォルトのストレージエンジンの自動置換を制御します。
ストレージエンジンは実行時にプラグイン可能である可能性があるため、使用できないエンジンは同じように扱われます。
NO_ENGINE_SUBSTITUTIONを無効にすると、CREATE TABLEではデフォルトのエンジンが使用され、目的のエンジンが使用できない場合は警告が表示されます。ALTER TABLEの場合、警告が発生し、テーブルは変更されません。
NO_ENGINE_SUBSTITUTIONを有効にすると、エラーが発生し、目的のエンジンが使用できない場合、テーブルは作成または変更されません。
- したがって、NO_ENGINE_SUBSTITUTIONが無効で、INNODBがオフになっている場合、CREATE TABLEステートメントでINNODBを指定した場合も、MySqlはMYISAMに切り替わります。
- 作成しているテーブルがMYISAMで問題ない場合は、警告が表示され、テーブルが作成されます。そうではありません。作成ステートメントにMYISAMの1000バイトの制限を超えるインデックスが含まれていると、作成が失敗し、エラー1071でMYISAMのエラーが報告されます。これは、動作するエンジンがINNODBではなくMYISAMであるためです。
証拠
MySqlバージョン5.1.56コミュニティ
ケース1:
Options in my.cnf
sql-mode=""
default-storage-engine=MYISAM
skip-innodb uncommented (without#)
Return on execution of your create statement:
Error Code: 1071. Specified key was too long; max key length is 1000 bytes
Explanation: INNODB is not active, the engine is automatically switched to MYISAM
that returns this error as they key is longer than MYISAM 1000 bytes limit.
The key length is:
2 fields x 255 char x 3 bytes utf8 encoding + 2 x 1 length byte = 1532 bytes
ケース2:
Options in my.cnf
sql-mode="NO_ENGINE_SUBSTITUTION"
default-storage-engine=MYISAM
skip-innodb uncommented (without#)
Return on execution of your create statement:
Error Code: 1286. Unknown table engine 'INNODB'
Explanation: INNODB is not active but the engine substitution is not permitted
by sql mode therefore the DB returns an error about the attempt of using a disabled engine.
ケース3:
Options in my.cnf
sql-mode="NO_ENGINE_SUBSTITUTION"
default-storage-engine=MYISAM
skip-innodb commented (with#)
Return on execution of your create statement:
Table creation OK!
Explanation: INNODB is active (skip-innodb commented) and it is used also if
the default engine is MYISAM.
テストを再現するには、my.cnfを変更するたびにMySqlを再起動します。
MySqlバージョン5.6sqlmodeはデフォルトで空ではなくなり、NO_ENGINE_SUBSTITUTIONが含まれているため、さらにINNODBがデフォルトのエンジンであるため、エラーを検出するのは困難です。
その他のテスト
エラーを再現する他の方法はありません:
Error Code: 1071. Specified key was too long; max key length is 1000 bytes
INNODBテーブルを作成しようとしているときに見つかりました。
INNODBには、2種類のエラー1071があります。
Error Code: 1071. Specified key was too long; max key length is 767 bytes
これは、innodb_large_prefixのONまたはOFFとは関係ありませんが、インデックスとして使用されている単一のVARCHAR列のサイズにのみ関係します。
Mysqlはvarcharutf8を3バイトに加えて255文字までの長さで1バイト、その後に2バイトを格納します(http://dev.mysql.com/doc/refman/5.7/en/storage-requirements.htmlを参照)。次のようなVARCHAR(256)utf8でキーを設定してみてください。
256 x 3 + 2 = 770 bytes
InnoDBテーブルの単一列の最大キー長は767バイトであるため、前のエラーが発生します。VARCHAR(255)は、次の理由で問題ありません。
255 x 3 + 1 = 766 bytes
Mysqlの4つのインストール、バージョン5.1.56、5.5.33、5.6、および5.7でテストしましたが、それが確認されています。VARCHAR(255)でのクエリ、VARCHAR(256)での問題はありません。
Error Code: 1071. Specified key was too long; max key length is 767 bytes
ご覧のとおり、メッセージはMYISAMではなくINNODBメッセージであるため、異なります。
INNODBテーブルのその他のタイプのERROR1071は次のとおりです。
Error Code: 1071. Specified key was too long; max key length is 3072 bytes
これは、複数の列を持つキーに関連しています。これらのキーを有効にするには、innodb_large_prefixをonに設定する必要があります。とにかく、あなたがこのような何かを実行しようとすると:
CREATE TABLE `phppos_modules_actions` (
`action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`action_name_key1` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`action_name_key2` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`sort` INT NOT NULL ,
PRIMARY KEY ( `action_id` , `module_id`, `action_name_key`, `action_name_key1`, `action_name_key2` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;
5つのVARCHAR(255)utf8列のキー(3830バイト)を使用すると、次のようになります。
Error Code: 1071. Specified key was too long; max key length is 3072 bytes
エキゾチックな仮説
原因の調査中に、私はさまざまでかなり奇妙な仮説を立ててテストしました。
ROW形式
テスト済みの冗長、コンパクト、圧縮、動的:ステートメントによるテーブル作成への影響はありません。
ファイル形式
テスト済みのアンテロープとバラクーダ:ステートメントによるテーブル作成への影響はありません。
MySqlが構築されました
テスト済みの32ビットおよび64ビットのMySql:ステートメントによるテーブル作成への影響はありません。
他の同様の失敗
ここでは、同じ状況で同じエラーを見つけることができます。
https://www.drupal.org/node/2466287
私はPROOFにリストされている3つのテスト状況でそのステートメントをテストしましたが、それはあなたとまったく同じ動作を再現したので、問題は同じであると言えます。その場合、他のDBに切り替えましたが、問題はDBバージョンではなく、設定の組み合わせです。
参考文献
INNODBを使用したインデックス作成の非常に優れた記事がここにあります。
http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/
警告:インデックスが1000より長いINNODBテーブルを作成した後、my.cnfでskip-innodbのコメントを解除してINNODBを無効にすると、MySqlサービスの開始が許可されません。
よろしく