2

我有一个长时间运行的 SQL 语句,当我从本地 Docker 容器内针对 AWS RDS 实例运行它时会超时。

我有一个.env文件,它定义了运行命令所需的一些环境变量。

我这样进入 Docker 容器:

docker run -i -t --env-file .env mysql:8.0.20 /bin/bash

进入容器后,我运行一个长时间运行的 SQL 命令,该命令在大约 5 分钟后始终超时。

mysql \
    mydatabase \
    --host=${MYSQL_RDS_HOST} \
    --port=3306 \
    --user=${MYSQL_USER} \
    --password=${MYSQL_PASSWORD} << EOF
        INSERT INTO copy_of_really_big_table (
            id, columna, columnb, columnc
        )
        SELECT id, columna, columnb, columnc FROM really_big_table;
EOF

我收到的错误是ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query.

我可以看到查询在 RDS 实例上运行,show processlist因此我知道查询正在通过 RDS。一旦发生超时,查询将继续运行直至完成。

我努力了:

  • --reconnectmysql命令行上提供
  • net_read_timeout在 MySQL 中奋起直追
  • net_write_timeout在 MySQL 中奋起直追
  • connection_timeout在 MySQL 中奋起直追
  • wait_timeout在 MySQL 中奋起直追
  • interactive_timeout在 MySQL 中奋起直追

虽然我怀疑这一切都是徒劳的,因为我可以从我的桌面(在 Docker 容器之外)运行命令。大约需要一个小时,但运行完成没有问题。

如果我从本地 Docker 容器内部针对另一个本地 MySQL Docker 容器运行 SQL 语句,它也会成功运行。

我已经在 Windows 和 Mac 上复制了这个问题。MySQL RDS 版本为 8.0.20。Docker 容器 MySQL 也是 8.0.20。

我真的希望我的本地容器上配置不正确。是否有网络超时设置?或者也许我没有正确路由?或者我没有看到 RDS 设置?

任何帮助将不胜感激,尤其是有关如何实际调试此类问题的提示。谢谢!

4

1 回答 1

0

调整net.ipv4.tcp_keepalive_time为我解决了这个问题。默认值为 7200 秒,但vpnKitMaxPortIdleTime在 Docker for Mac 中默认为 300 秒,这允许端口超时。

docker run -i -t --env-file .env --sysctl net.ipv4.tcp_keepalive_time=150 mysql:8.0.20 /bin/bash

我用了 150 秒,但少于 300 秒就足够了。

于 2021-07-08T17:04:16.027 回答