当查询以分号结束时,为什么最大查询大小不同?

c9x0cxw0  于 2021-06-20  发布在  Mysql
关注(0)|答案(0)|浏览(185)

如果你环顾互联网(例如mysql的最大查询大小是多少?),你会发现mariadb/mysql的最大查询大小等于 max_allowed_packet 变量。但当你真的尝试了,你会发现这并不完全正确。
下面是一个生成所需大小的测试查询的小lua脚本:

prefix = "SELECT IF(0,'"
postfix = "',NULL);"
max_allowed_packet = 16777216 -- The value for my setup

function gen_query(size)
    local n = size - string.len(prefix) - string.len(postfix)
    local query = prefix .. string.rep('X', n) .. postfix
    io.open("/tmp/testquery.sql", "w"):write(query):close()
end

gen_query(max_allowed_packet)
``` `/tmp/testquery.sql` 现在包含如下查询 `SELECT IF(0,'<a lot of Xs here>',NULL);` .
如果我们现在尝试执行此操作,将得到一个错误:

$ mysql -A -B < /tmp/testquery.sql
ERROR 1153 (08S01) at line 1: Got a packet bigger than 'max_allowed_packet' bytes

如果我们做同样的事,但是 `gen_query(max_allowed_packet - 1)` (生成一个小一个字节的查询),服务器将愉快地执行查询:

$ mysql -uroot -pmysql --protocol=tcp -A -B < /tmp/testquery.sql
IF(0,'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
NULL

如果我们仔细研究mysql的文档(找不到mariadb的等价物),这就开始有意义了,因为数据包包含一个额外的字节(0x03),该字节将数据包声明为 `COM_QUERY` 小包裹:https://dev.mysql.com/doc/internals/en/com-query.html
到目前为止,这一切对我来说都是有意义的,但是如果我们继续修改lua程序,使其在末尾不包含分号(通过设置 `postfix = "',NULL)"` ),突然又是这样的结果:

$ mysql -uroot -pmysql --protocol=tcp -A -B < /tmp/testquery.sql
ERROR 1153 (08S01) at line 1: Got a packet bigger than 'max_allowed_packet' bytes

测试查询仍然是最大\u允许的\u数据包-1字节长:

$ wc -c /tmp/testquery.sql
16777215 /tmp/testquery.sql

一个最大\u允许的\u数据包-不带分号的2字节长的查询再次按预期工作。
怎么回事?是吗 `mysql` 命令行客户机/mysql库自动插入 `;` 最后?据我所知,事实并非如此,以下是strace输出的摘录:

$ strace -v -e write=3 mysql -A -B < /tmp/testquery.sql
<<< irrelevant syscalls omitted >>>
sendto(3, "\377\377\377\0\3SELECT IF(0,'XXXXXXXXXXXXXX"..., 16384, 0, NULL, 0) = 16384
| 00000 ff ff ff 00 03 53 45 4c 45 43 54 20 49 46 28 30 .....SELECT IF(0 |
| 00010 2c 27 58 58 58 58 58 58 58 58 58 58 58 58 58 58 ,'XXXXXXXXXXXXXX |
<<< lots of hexdump data omitted >>>
| ffbff0 58 58 58 58 58 58 58 58 58 58 58 58 27 2c 20 4e XXXXXXXXXXXX', N |
| ffc000 55 4c 4c ULL |
sendto(3, "\1\0\0\1)", 5, 0, NULL, 0) = 5
| 00000 01 00 00 01 29 ....) |
<<< more irrelevant syscalls omitted >>>

我是否可以发送一个最大允许数据包长度为2字节的查询,并且总是希望它正常工作(当然,假设sql查询中没有错误:)?这种行为有记录吗?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题