在导入大文件时,aws rds,在查询期间丢失了与MySQL服务器的连接

我尝试将一个1.4G的 mysql文件导入到aws rds中.我尝试了2 cpu和4G mem选项.我仍然遇到错误:在查询期间丢失了与 MySQL服务器的连接.我的问题是如何将大型mysql文件导入rds. 最佳答案 MySQL服务器和MySQL客户端都有一个参数max_allowed_pa​​cket.

这被设计为安全检查,以防止在数据损坏导致连接的接收端认为数据包¹非常大的情况下可能发生的大量内存的无用和破坏性分配.

在传输查询和结果集时,客户端和服务器都不允许发送大于max_allowed_pa​​cket的任何单个“东西”(通常是查询或列的值) – 发送方将抛出错误并拒绝发送它如果你尝试,接收方将抛出一个错误,然后关闭你的连接(所以客户端可能会或可能不会实际报告错误抛出 – 它可能只是报告连接丢失).

不幸的是,同一参数的客户端设置和服务器设置是两个独立的设置,并且它们是不协调的.技术上并不要求它们是相同的,但只有当它们都没有超过另一个所施加的限制时,差异值才起作用.

更糟糕的是,他们的默认值实际上是不同的.在最近的版本中,服务器默认为4 MiB,而客户端默认为16 MiB.

找到服务器的值(SELECT @@ MAX_ALLOWED_PACKET),然后设置客户端以匹配服务器(mysql –max-allowed-packet = max_size_in_bytes)将通过导致客户端“修复”查询错误消息期间与MySQL服务器的神秘丢失连接to Do The Thing™并且不会尝试发送服务器不接受的数据包.但是你仍然会收到一个错误 – 只是一个信息更丰富的错误.

因此,我们需要将双方重新配置为更合适的东西……但我们如何知道正确的价值呢?

你必须知道你的数据.任何列中最大可能的值是多少?如果这是一个延伸(在许多情况下,它是),您可以简单地从基于转储文件中最长行的相当大的值开始.

使用这个单行找到:

$perl -ne '$max = length($_) > $max ? length($_) : $max; END { print "$max\n" }' dumpfile.sql

输出将是文件中最长行的长度(以字节为单位).

您可能希望将其四舍五入到下一个2的幂,或者至少下一个1024的增量(1024是服务器接受的粒度 – 值是舍入的)或者您认为合适的任何内容,但是这个结果应该给出您应该允许您加载转储文件而没有问题的值.

现在我们已经建立了一个应该工作的新值,将服务器上的max_allowed_pa​​cket更改为您刚刚发现的新值.在RDS中,这是在参数组中完成的.确保该值已应用于您的服务器(SELECT @@ GLOBAL.MAX_ALLOWED_PACKET;).

然后,您需要将相同的值传递给您的客户端程序,例如如果此值小于默认客户端值,则mysql –max-allowed-packet = 33554432.您可以使用以下命令找到默认客户端值:

$mysql --help --verbose | grep '^max.allowed.packet'
max-allowed-packet                16777216

客户端还允许您以SI单位指定值,例如–max-allowed-packet = 32M(32 MiB)(33554432字节).

这个参数 – 以及它们中的两个,一个用于客户端,一个用于服务器 – 这一事实引起了很多混乱,并导致一些不良信息的传播:你会发现互联网上的人告诉你把它设置为像1G这样荒谬的值(1073741824,这是可能的最大值),但这不是一个非常好的策略,因为如上所述,这是一种保护机制.如果一个数据包碰巧在网络上以错误的方式被破坏,服务器可能会断定它实际上需要分配大量的内存,以便这个数据包可以成功加载到缓冲区 – 这可能导致通过使系统缺乏可用内存来减少系统损害或拒绝服务.

服务器通常为从线路读取数据包分配的实际内存量是net_buffer_length.除非它大于net_buffer_length,否则数据包中指示的大小实际上不会被分配.

¹数据包是指MySQL客户端/服务器协议意义上的第7层数据包.不要与IP数据包或数据报混淆.

点赞