使用mysqldump时即使有max_allowed_packet参数也会出现失去与mysql的连接问题

31

我想在我的远程服务器数据库中转储特定的表,这个操作可以正常工作,但其中一个表有900万行数据,导致出现以下错误:

Lost connection to MySQL server during query when dumping table `table_name` at row: 2002359
所以在网上阅读后,我了解到需要增加我的max_allowed_packet,并且可以将其添加到我的命令中。 因此,我正在运行以下命令来转储我的表格:
mysqldump -uroot -h my.host -p'mypassword' --max_allowed_packet=512M db_name table_name | gzip  > dump_test.sql.gz

出于某种原因,我仍然得到:

Lost connection to MySQL server during query when dumping table `table_name` at row: 2602499

我做错了什么吗?

很奇怪,只有900万记录...不算太大。

7个回答

51

尝试在您的mysqldump命令中添加--quick选项;它与大型表格配合效果更好。它会将结果集中的行直接流式传输到输出,而不是一次性将整个表读入内存,然后写出。

 mysqldump -uroot -h my.host -p'mypassword' --quick --max_allowed_packet=512M db_name table_name | \
 gzip  > dump_test.sql.gz

你也可以尝试在你的 mysqldump 命令中添加 --compress 选项。这使其使用更加网络友好的压缩连接协议到 MySQL 服务器。请注意,你仍然需要使用 gzip 管道;MySQL 的压缩协议不会导致从 mysqldump 导出的转储文件是压缩的。

另外,可能是服务器将其与 mysqldump 客户端的连接超时了。你可以尝试重置超时时间。通过其他方式连接到服务器并发出这些查询,然后再运行你的 mysqldump 作业。

这些设置将超时时间设置为一天。

    SET GLOBAL wait_timeout=86400;
    SET GLOBAL interactive_timeout=86400;

如果您的服务器与您的计算机相隔甚远(通过路由器和防火墙),可能会有一些干扰 mysqldump 的连接。有些较劣的路由器和防火墙对NAT(网络地址转换)会话设置了时间限制。它们应该在使用时保持这些会话活动状态,但有些不会。或者您可能正在击中公司为外部连接配置的时间或大小限制。

尝试登录到靠近服务器的机器上并在其上运行 mysqldump。然后使用其他方法(例如sftp)将gz文件复制到自己的计算机上。

或者,您可能需要分段转储此文件。您可以执行类似于以下内容的操作(未调试)。

mysqldump  -uroot -h my.host -p'mypassword'  \ 
          db_name table_name --skip-create-options --skip-add-drop-table \
          --where="id>=0 AND id < 1000000" | \
          gzip....

然后用这些行重复一遍。

          --where="id>=1000000 AND id < 2000000" | \

          --where="id>=2000000 AND id < 3000000" | \
          ...

直到你获得所有的行。虽然有点繁琐,但这样做是有效的。


1
它存活了一段时间,但仍然在转储表格table_name的第2926704行时出现了Lost connection to MySQL server during query错误。这让我感到非常烦恼... - JohnBigs
请查看我的详细回答。 - O. Jones
2
谢谢伙计,我认为--compress起了作用:) 感谢@O. Jones - JohnBigs

6

当我跳过锁定表时,一切都正常工作。

 mysqldump -u xxxxx --password=xxxxx --quick --max_allowed_packet=512M --skip-lock-tables --verbose   -h xxx.xxx.xxx.xxx > db.sql

可能我存在一致性问题,但是我可以毫无问题地备份一个5GB的数据库。


3

其他尝试的选择:

net_read_timeout=3600 
net_write_timeout=3600

在my.ini/my.cnf文件中或通过SET GLOBAL ...设置全局变量。

2

根据JohnBigs的评论所述,--compress 标志对我有用。

之前我尝试了 --single-transaction--skip-extended-insert--quick,但都没有成功。

注:Original Answer 翻译成“最初的回答”


1
同时,请确保您的MYSQL.EXE客户端与您的mysql服务器版本相同。
因此,如果您的mysql版本为8.0.23,但客户端版本为8.0.17或8.0.25,则可能会遇到问题。我曾遇到这个问题,在mysql服务器8.0.23上使用8.0.17版本 - 将客户端版本更改为与服务器版本相匹配解决了该问题。

1
这就是我的全部内容。使用mysqldump版本8连接到mysql服务器5.6。 - user2966697

0

我在我的服务器上遇到了类似的问题,在夜间备份期间MySQL似乎会重新启动。它总是相同的数据库,但实际的表有时会有所变化。

尝试了这里其他答案中的几个方法,但最终只是一些cronjob执行未完成的查询。这导致CPU和RAM使用率不高,无法触发监控,但显然足以导致压缩转储时OOM killer变为活动状态。修复了cronjob后,下一个备份就可以正常进行了。

需要查看的内容:

  • OOM?dmesg | grep invoked
  • 被杀死进程?grep killed /var/log/kern.log

-1

如果其他方法都不行,你可以使用 mysqldumpwhere 功能,将你的大查询拆分成多个小查询。

这可能会有些繁琐,但很可能会起作用。

例如:

"C:\Program Files\MySQL\MySQL Workbench 8.0 CE\mysqldump.exe" --defaults-file="C:\...\my_password.cnf" 

--host=localhost --protocol=tcp --user=mydbuser --compress=TRUE --port=16861 --default-character-set=utf8 --quick --complete-insert --replace 

--where="last_modify > '2022-01-01 00:00:00'" 

> "C:\...\dump.txt"

my_password.cnf

[client]
password=xxxxxxxx

[mysqldump]
ignore-table=db.table1
ignore-table=db.table2

然后,您只需修改last_modify列,将其向未来进一步移动,您的大表现在已经分成了许多小表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接