MySQL Insert資料量過大導致報錯 MySQL server has gone away

tong發表於2019-02-16

接手了同事的專案,其中有一個功能是儲存郵件模板(包含圖片),同事之前的做法是把圖片進行base64編碼然後存在mysql資料庫中(欄位型別為mediumtext)
然後儲存三張圖片(大概400k)的時候報錯
MySQL server has gone away

然後檢視官方文件https://dev.mysql.com/doc/ref…

得知可能是以下幾個原因 
伺服器超時
伺服器斷開
向伺服器傳送不正確或太大的查詢
INSERT或者 REPLACE是插入大量行

開始以為是伺服器超時導致的,在網上搜的解決辦法(好吧,先試一下 ,發現還是不行):

<?php
$dbh = new PDO(`mysql:host=localhost;dbname=test`, $user, $pass, array(
                                        PDO::ATTR_PERSISTENT => true
));
?>
Note:
如果想使用持久連線,必須在傳遞給 PDO 建構函式的驅動選項陣列中設定 PDO::ATTR_PERSISTENT 。如果是在物件初始化之後用 PDO::setAttribute() 設定此屬性,則驅動程式將不會使用持久連線。

直接在Navicat上執行sql語句,報錯 [Err] 1153 – Got a packet bigger than `max_allowed_packet` bytes
搜尋得知:當MySQL客戶端或mysqld伺服器收到大於max_allowed_packet位元組的資訊包時,將發出“資訊包過大”錯誤,並關閉連線。對於某些客戶端,如果通訊資訊包過大,在執行查詢期間,可能會遇到“丟失與MySQL伺服器的連線”錯誤。
客戶端和伺服器均有自己的max_allowed_packet變數,因此,如你打算處理大的資訊包,必須增加客戶端和伺服器上的該變數。一般情況下,伺服器預設max-allowed-packet為1MB
這下問題精確定位了,就是max_allowed_packet配置的問題,

查一下配置 show VARIABLES like `%max_allowed_packet%`; 發現是1048576(1024*1024),也就是1MB,
但是我的圖片才400K,不應該啊,然後網上一查:Base64-encoded 資料要比原始資料多佔用 33% 左右的空間。
還是不確定,直接strlen()返回base64字串長度1451334,utf8編碼下英文字元1字元佔1位元組,所以base64編碼後是1451334B(這個是我自己的理解),大於1MB

修改max_allowed_packet配置 set global max_allowed_packet = 410241024;

發現問題完美解決

相關文章