Go&MySQL`max_allowed_packet`

当发送给数据库的语句过大时,会报如下错误:

1
panic: Error 1105: Parameter of prepared statement which is set through mysql_send_long_data() is longer than 'max_allowed_packet' bytes

从报错中可知,需要修改 max_allowed_packet 选项的值。

my.cnf

在 my.cnf 配置文件中修改该选项是最直接了当的,修改成合适的值后重启服务即可。

1
2
[mysqld]
max_allowed_packet=16M

会话

当打开一个会话时,也可以使用下面的语句设置全局或当前的 max_allowed_packet 值。

1
2
SET GLOBAL max_allowed_packet=1073741824;
SET max_allowed_packet=1073741824;

第 1 个在服务重启后失效,第 2 个在会话结束会失效。

go-sql-driver/mysql

更多情况下,还是希望在程序中控制该选项,所以要看下使用的数据库驱动是否支持该选项。很庆幸,go-sql-driver/mysql 是支持的,使用的版本如下:

1
go-sql-driver/mysql@v1.6.0

在使用 gorm 中,返回一个 *gorm.DB 实例,我们都会使用下面的代码:

1
db, err := gorm.Open(mysql.Open("username:password@tcp(host:port)/database?queryString"), &gorm.Config{})

下面说一下整行代码的执行顺序:

  1. mysql.Open 简单返回一个实现 gorm.Dialector 接口的实例(只是简单的赋值,并没有作解析);
  2. gorm.Open 会调用 Dialector.Initialize 方法,并且会真正地打开数据库连接;
1
db.ConnPool, err = sql.Open(dialector.DriverName, dialector.DSN)
  1. 在 sql.Open 中会调用;
1
connector, err := driverCtx.OpenConnector(dataSourceName)
  1. 在 driverCtx.OpenConnector 中会调用 ParseDSN 方法;
  2. ParseDSN 完成了对 DSN 的解析,包括 queryString 部分;

即:

1
2
3
4
mysql.Open
\
 \ gorm.Open -> Dialector.Initialize -> sql.Open -> driverCtx.OpenConnector
                                                 -> ParseDSN

go-sql-driver/mysql 支持的 query 参数包括如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
allowAllFiles
allowCleartextPasswords
allowNativePasswords
allowOldPasswords
checkConnLiveness
clientFoundRows
collation
columnsWithAlias
compress # 这个是没有实现的
interpolateParams
loc
multiStatements
parseTime
readTimeout
rejectReadOnly
serverPubKey
strict
timeout
tls
writeTimeout
maxAllowedPacket

参考

  1. max_allowed_packet in mySQLmax_allowed_packet in mySQL