出典について
この記事は「Inserting large rows in MySQL and MariaDB」(2015/7/20)を翻訳したものである。
MySQLにおけるLONGBLOBの最大容量は4GBであり、max_allowed_packetの最大値のサイズは1GBである為、私はLONGBLOBを完全に使いきることができるのだろうかと思い立った。
そこでこれをテストし始めた。MySQL Connector/Pythonを使ってPythonスクリプトを書き、MySQL Sandboxを使ってMySQL 5.6.25のインスタンスを作成した。
最初に変えるべき設定はmax_allowed_packetであり、これは予想通りであった。この値は1GBに設定した。
次の設定は、少し予想通りではなくなり、innodb_log_file_sizeであった。InnoDBログファイルの10%以下のサイズにトランザクションが収まるようにサーバが制限するのだ。従って、(だいたい)1GBの1レコードが挿入できるように、5GBのファイルが2つとなるように設定した。
パケット内部にはいくらかのオーバーヘッドがあるため、1GBより少し小さい行を扱い、1GBちょうどになるようにした。
(1GBへの)次のステップは、複数のチャンクを使ったデータアップロードを可能とするmysql_stmt_send_log_data()関数を使えるようにするため、PythonをやめてC言語に切り替えた。
これはうまく動作するだろうと期待していたが、実際は動作しなかった。これはMySQL 5.6またはそれ以上では、max_long_data_sizeがmax_allowed_packetに置き換えられていた為だ。 しかし、max_long_data_sizeは4GBに設定できるのに対し、max_allowed_packetは最大1GBまでしか設定できないのだ。
そこで、MySQL 5.6からMariaDB 10.1に切り替えた。MariaDBではmax_long_data_sizeがまだ利用できたためだ。これで動作させることができ、(おおよそ)4GBの行をアップロードすることができた。
私はInnoDBが大きなタプルに対してエラーログを出力することにも気付いた。
InnoDB: Warning: tuple size very big: 1100000025
従って、CDのISOイメージはデータベースに挿入することができる。小さなDVDイメージに関しては、ご利用のコネクタがCOM_STMT_SEND_LONG_DATAコマンドを使っている場合にうまく動作する。
しかしながらこれは避けて、行のサイズが小さくなるようにした方が良いだろう。
テストで使ったスクリプト(と見つけたバグへのリファレンス)は下記の通りである。 https://github.com/dveeden/mysql_supersize