MySQLのmax_allowed_packetについて
先日、カイシャのギョームでこんなことがあった。
「なんか、普通に投稿はできるんだけど、下書きが保存できないんだよね。ちょっと原因わからない?」
Railsで書かれている対象のコードを読んだのだが、まったく問題がなさそうだ。普通に ActiveRecord
のメソッドを読んでテキスト情報を保存しているだけだからだ。
今扱っているプロジェクトは負債が多くてどこが本当に原因なのかはわからなかったので途方に暮れていたら、カイシャの凄腕の人が「多分 max_allowed_packet
かな」と言い、サクッと直してしまった。
こういうのが技術力なんだなぁとしみじみ思ったので、どういうことが起こっていたのかちゃんと復習して、次同じようなことが合った時ドヤ顔できるようにする(間違いがあるかもなので指摘してもらえると幸い)
まず、対象の table
を show create table
するとこんな感じだった(一部抜粋)
CREATE TABLE `drafts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dump_obj_encode_in_base64` longtext NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
) ENGINEInnoDB AUTO_INCREMENT~145 DEFAULT CHARSET~utf8 ROW_FORMAT~DYNAMIC
引き継いだプログラムなのでなぜこうなっていたのかまったくわからないが、 dump_obj_encode_in_base64
の型が longtext
で保存されていた。
longtext
は 最長4,294,967,295、または4GB (232 - 1) バイト
と非常にsizeが大きい。
MySQLのclientがserver投げられる最大のデータ量はどのくらいだろうか。
それを定義しているのが max_allowed_packet
だ。
現在このブログを書いているPCのMySQL(Server version: 5.7.25-0ubuntu0.18.04.2 (Ubuntu)
)はどうだろうか。
mysql> show variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set (0.06 sec)
約16MBだった。 longtext
では全然足りないサイズだ。
RDSはAWS Consoleで変更できたので、ユーザーの少ない時間に再起動をして問題なく動き始めた。
gem: mysql2
では今のエラーを以下のように表現している。
https://github.com/brianmario/mysql2/blob/master/lib/mysql2/error.rb#L18
1153 => ConnectionError, # ER_NET_PACKET_TOO_LARGE
packet too large
は connection error
になってた。
これはわからない。
カイシャの凄腕の人が言ってたことを忘れないようにメモをしておく。
ピンポイントで下書きでエラーが出てる
↓
下書きテーブルに何かあるのでは&接続が切れるといえばタイムアウト・コネクション数・パケット長のどれか
↓
テーブルを見るとlongtextがある
ちなみにmax_allowed_packetを上げると、MySQLにデータ(SQL文)を流し込む時間も当然長くなるので
今度はそこでタイムアウトする懸念があります
net_write_timeout/net_read_timeoutね