MariaDB系统变量限制测量对象:原始数据还是SQL字符串?
我来帮你理清这几个MariaDB系统变量到底限制的是什么数据——这确实是批量写入场景里很容易混淆的点,咱们一个个拆解清楚:
innodb_buffer_pool_size
这个变量和你说的“传输的原始参数”或“SQL字符串字节数”完全无关。它是InnoDB存储引擎用来缓存表数据、索引、自适应哈希索引等核心数据的内存池大小。简单说,就是InnoDB把磁盘上的数据页加载到内存里,方便快速读写,这个变量就是给这个内存区域分配的总大小。批量写入时,它影响的是数据写入磁盘前的缓存效率,不会直接限制你能写入的单条或批量数据的大小。
innodb_log_buffer_size
这个是InnoDB的重做日志缓冲区,它缓存的是待写入磁盘重做日志文件(ib_logfile)的日志记录。这些日志记录是基于你实际修改的行数据(也就是你说的原始参数对应的变更内容),而不是完整的SQL字符串。比如你执行UPDATE data SET value = 0.1234 WHERE date = '2012-01-01',InnoDB会把“将date为'2012-01-01'的行的value字段更新为0.1234”这个变更操作的日志写到缓冲区,而不是整个UPDATE语句的字符串。当缓冲区满了或者达到触发条件时,这些日志会被刷到磁盘。所以这个变量限制的是待刷盘的重做日志的总大小,和SQL语句本身的长度没有关系。
max_allowed_packet
这个是最容易搞混的,也是直接和你传输的内容大小相关的变量:
- 默认情况下(使用普通的SQL语句,不是预处理语句),它限制的是从客户端发送到服务器的单个SQL请求数据包的总字节数——也就是完整的SQL字符串的大小,包括关键字(比如UPDATE、INSERT)、表名、WHERE条件、SET子句,以及所有参数值的字符串表示(比如你例子里的
'2012-01-01'、0.1234这些的字符形式)。所以你说的“后者(完整SQL字符串)大小是前者(原始参数)的2-3倍”的情况,这个变量会以完整SQL字符串的大小来判断是否超限。 - 如果用预处理语句(Prepared Statements),情况会不一样:SQL模板(比如
UPDATE data SET value = ? WHERE date = ?)和参数是分开传输的。这时候max_allowed_packet会分别限制两个部分的大小:SQL模板的数据包大小,以及每个参数批次的数据包大小。这时候参数部分的大小就是你说的“原始参数值”的字节数(或者更准确地说,是参数的二进制表示大小),而不是拼接后的完整SQL字符串。
结合你的5万行批量操作场景补充一句:如果是用单条SQL拼接所有行(比如INSERT INTO ... VALUES (...), (...), ...),那整个超长的SQL字符串的总大小必须小于max_allowed_packet;如果是用预处理批量执行(比如每次绑定一批参数执行),那每个参数批次的数据包大小不能超过这个变量,而SQL模板本身很小,基本不会触发限制。
内容的提问来源于stack exchange,提问作者Adam

