web-dev-qa-db-ja.com

MySQL 5.7で行サイズが8126より大きいテーブルを保持するリスクは何ですか?

MySQL 5.6から5.7にアップグレードしたところ、WordPressプラグインテーブルにとんでもない438フィールドが含まれ、行サイズの上限である8126バイトを超えていることがわかりました。

mysql_upgradeの実行時に受け取った警告は次のとおりです。

行サイズが大きすぎます(> 8126)。一部の列をTEXTまたはBLOBに変更するか、ROW_FORMAT = DYNAMICまたはROW_FORMAT = COMPRESSEDを使用すると役立つ場合があります。現在の行形式では、768バイトのBLOBプレフィックスがインラインで格納されます。

これは単なる警告でしたが、テーブルはまだ残っています。 同じ構造で新しいテーブルを作成することはできませんが、興味深いことに、古いテーブルを保持できますそしてそれを使用します(少なくともSELECTから)。

私は同様のトピックについて RolandoMySQLDBA's および Bill Karwin's の回答を読みましたが、解決策はありません:

  • ROW_FORMAT=DYNAMICに変更するだけでは十分ではありません。テーブルには、最大サイズを超えるインラインUTF-8 VARCHARフィールドだけが含まれているためです。
  • テーブルの構造を変更することは、サードパーティのソフトウェアの一部であるため、問題外です。これは、ワームの缶を開くようなものです。

私はプラグイン開発者にエラーを報告し、彼らがテーブルをすぐに修正することを望んでいますが、それまでの間、私はこの無法者テーブルで立ち往生しています。

だから質問は:

  • MySQLは、そのようなテーブルを作成することを許可しない場合、InnoDBストレージルールを尊重しないテーブルをどのように処理できますか?
  • テーブルを現在の状態に保つリスクはありますか?
  • このテーブルで実行できるクエリのタイプに制限はありますか?
  • このサーバーを別のMySQL 5.7サーバーに複製すると、このテーブルが原因で複製が失敗しますか?

MySQL 5.6からアップグレードしました。私はDYNAMICおよびCOMPRESSED形式を試しましたが、うまくいきませんでした。 integer + varcharフィールドのサイズを計算しました。合計は17,059バイトなので、この方法で成功することはできません。

プラグインは フォトギャラリー と呼ばれ、障害のあるテーブルはwp_bwg_themeです。

5
Benjamin
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=ON;
ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- Or COMPRESSED

それが5.6で必要だったと思います。 Barracudaとfile_per_tableは5.7のデフォルトであるため、これのほとんどはなくなります。ただし、アップグレードによってテーブルAntelopeが残されたり、file_per_tableが残されなかったりする場合があります。

したがって、これら3つのコマンドをスローして、問題が完全に「修正」されるかどうかを確認することをお勧めします。 (ええ、ある種のバックアップを最初にどこかに保管してください。)

あなたはutf8に言及しました。おそらくあなたもutf8mb4が欲しいですか?

ALTER TABLE tbl CONVERT TO utf8mb4;

(レプリケーションが問題になるかどうかは今はわかりません。おそらく上記の変更後は、5.7スレーブでは問題にならないでしょう。)

編集

しかし...(5.7の)デフォルトであることはではないは、アップグレード後に存在するファイルのそれらの値を得たことを意味します。

覗く information_schema.INNODB_SYS_TABLESfile_formatおよびrow_formatです。列spaceは、値が0より大きい場合にfile_per_tableを示します。

この問題に対処する抜本的な方法:InnoDBページサイズを変更します。デフォルトは16KBですが、32KBも可能です。私が間違っていない場合は、システム上のallテーブルを新しいページサイズに変換する必要があるため、それは重要な作業であり、その他の影響がある可能性があります。

VARCHAR/DYNAMICでのCOMPRESSEDの処理

文字列がレコードの他のブロックに保存されるのに対して、レコードのメイン部分に保存されるのはいつですか?

  • 小さいサイズ(文字列は40バイト未満):文字列全体がレコードとともに保存されます。 2 + Nバイト。
  • 中サイズ:「レコードが大きすぎない」に応じて、「小さい」または「大きい」のいずれか。
  • 大きいサイズ:レコード内で2 + 20バイト(長さ+ポインター);テキスト全体が個別に保存されます。

「レコードが大きすぎます」:行が長すぎる場合、最も長い列がページ外ストレージに格納されます。つまり、行全体の構成によっては、列が完全にページ外になる場合もあれば、ページ上になる場合もあります。

VARCHARTEXTBLOBは、DYNAMICまたはCOMPRESSEDと同じように処理されます。

DYNAMIC形式は、長いデータ値の一部がページ外に格納される場合、通常はすべての値をページ外( "all or none")に格納するのが最も効率的であるという考えに基づいています。

COMPRESSED = DYNAMIC +圧縮。 KEY_BLOCK_SIZEは、クラスター化インデックスに格納される列データの量、およびオーバーフローページに配置される量を制御します。

5.7参照 および 古い、より詳細、説明 ;その他のページ。

2
Rick James

Rick Jamesの回答(彼の+1) を読んだ後、これに追加するのは、ROW_FORMAT=COMPRESSEDを使用する場合は、より大きなInnoDBバッファープールを構成することだけです。どうして ?

私は以前の投稿 innodb_file_format Barracuda で、アクセスするページの解凍に対応するためにバッファプールのサイズをどのように増やす必要があるかについて述べました。

自分の投稿 ...から盗用.

シナリオ

  • 8Gバッファープールを備えたDBサーバーがある
  • key_block_size=8 [.____を使用して圧縮を実行しました。]
    • 850.00%/16です
    • 50.00%/8G4Gです
    • innodb_buffer_pool_size12Gにレイズします(8G + 4G
  • key_block_size=4 [.____を使用して圧縮を実行しました。]
    • 425.00%/16です
    • 25.00%/8G2Gです
    • innodb_buffer_pool_size10Gにレイズします(8G + 2G
  • key_block_size=2 [.____を使用して圧縮を実行しました。]
    • 212.50%/16です
    • 12.50%/8G1Gです
    • innodb_buffer_pool_size9Gにレイズします(8G + 1G
  • key_block_size=1 [.____を使用して圧縮を実行しました。]
    • 106.25%/16です
    • 06.25%/8G0.5G512M)です
    • innodb_buffer_pool_size8704Mに累乗します(8G8192M)+ 512M

MORAL OF THE STORY:InnoDBバッファープールは、圧縮されたデータとインデックスページを処理するときに追加の呼吸スペースを必要とします。

1
RolandoMySQLDBA