私たちのサーバーは多くのテーブルを作成しており、そのうちの1つはLock_
テーブルです。
PerconaでMySQL 5.5を使用しています。また、utf8_general_ci
およびutf8
を使用しています。
Lock_
テーブルに次のインデックスを作成すると、次のエラーがスローされます。
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
次に、テーブル作成クエリを示します。
create table Lock_ (
uuid_ VARCHAR(75) null,
lockId LONG not null primary key,
companyId LONG,
userId LONG,
userName VARCHAR(75) null,
createDate DATE null,
className VARCHAR(75) null,
key_ VARCHAR(200) null,
owner VARCHAR(255) null,
inheritable BOOLEAN,
expirationDate DATE null
);
インデックスクエリ:
create unique index IX_DD635956 on Lock_ (className, key_, owner);
この問題は、prodサーバーの1つで発生しています(以前はスタンドアロンのmysqlでしたが、後でperconaに移動しましたが、問題は両方のエディションに存在していました)。ただし、これは私たちの開発環境では問題なく機能しています。
それで、このエラーをスローしないように、prod環境のインデックス長などを更新する方法はありますか?
ありがとう
違いはUnicodeの長さの問題だと思います。文字ごとに1バイトの照合順序を使用していないため、キー内のフィールドの合計長は530character(75 + 200 + 255 )および530bytesではなく、530文字は、それらの文字列に格納している言語に応じて、767バイトを超える可能性があります(実際、 mysqlが、MS SQL ServerがNVARCHARカラム型で行うように、Unicodeデータを常に文字あたり2バイトとして格納する場合)。
Devで動作しているがライブではない理由:
length()
関数( http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_length )はバイト数を返しますが、文字なので、LENGTH(className)+LENGTH(key)+LENGTH(owner) > 767
を選択して、そのような行をスキャンできます。(className, key_, owner)
に必要なインデックスサイズの合計:
(75*3 + 1 + 1) + (200*3 + 2 + 1) + (255*3 + 2 + 1) = 1598 bytes
InnoDB 各列のインデックスが最大767バイトの場合のみ、最大3500バイトのインデックスが許可されます 。 MyISAMは 合計1000文字 (ブロックサイズの変更)のみを許可します。 おそらく、本番データベースはInnoDBではなくMyISAMを使用しています。 多分あなたは本番でutf8mb4
を使用していますか?それはあなたにそのエラーをもたらすでしょう。
また、 なぜvarchar(255)をお勧めしないのか もご覧ください。