为什么我在直接访问 mysql 数据库时会收到这些随机超时错误

Why am i getting these random timeout errors on mysql database being accessed directly

我在同一台机器上安装了 Tomcat 和 Mysql,最近没有更新,所以我们使用 Tomcat 7.0.31 和 MySql 5.0。 Linux.

上 95

当用户进行购买时,由 Paypal 处理,然后他们联系我们的服务器,我们创建许可证并将其存储在数据库中,但不幸的是,它并不总是有效,会出现以下错误:

The last packet successfully received from the server was 44,533,707 milliseconds ago. The last packet sent successfully to the server was 44,533,707 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

但我不认为 MySql 挂了,因为我从来没有遇到过连接问题,大约 5% 的时间会随机出现错误。

Mysql 包含两个数据库实例,在我的 web.xml 文件中我有

<resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/jaikoz</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
  <description>DB Connection2</description>
  <res-ref-name>jdbc/songkong</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</resource-ref>

并且在context.xml(我已经更改了用户名和密码)我有

<Context path="/store" privileged="true">
    <Resource name="jdbc/jaikoz" auth="Container" type="javax.sql.DataSource"
              maxActive="-1" maxIdle="-1" maxWait="10000"
              username="usrnm" password="pwd" driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/jaikoz?autoReconnect=true"/>
    <Resource name="jdbc/songkong" auth="Container" type="javax.sql.DataSource"
              maxActive="-1" maxIdle="-1" maxWait="10000"
              username="usernm" password="pwd" driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/songkong?autoReconnect=true"/>
</Context>

此外,此配置来自我的 Store 网络应用程序,我还有一个 jaikoz 和一个 songkong Web 应用程序这两个都定义了其中一个连接。我不得不介绍 'store',因为支付提供商需要一个 url 来发送所有成功的付款(无论是来自 songkong 还是 jaikoz)

我想知道是否有两个数据库连接会破坏事情,或者让两个应用程序定义相同的连接是否会破坏事情,因为我认为当我只有 jaikoz 应用程序时我没有遇到这样的问题。

错误说我可以使用 AutorReconnect=true,但我已经在这样做了。

运行 按照提示显示进程列表,得到如下信息:

mysql> show processlist
    -> ;
+--------+------+-----------------+----------+---------+-------+-------+------------------+
| Id     | User | Host            | db       | Command | Time  | State | Info             |
+--------+------+-----------------+----------+---------+-------+-------+------------------+
| 127681 | paul | localhost:40360 | jaikoz   | Sleep   |     5 |       | NULL             |
| 127682 | paul | localhost:40361 | jaikoz   | Sleep   |     7 |       | NULL             |
| 127683 | paul | localhost:40362 | jaikoz   | Sleep   |    11 |       | NULL             |
| 127684 | paul | localhost:40363 | jaikoz   | Sleep   |     2 |       | NULL             |
| 127685 | paul | localhost:40364 | jaikoz   | Sleep   |    17 |       | NULL             |
| 127754 | paul | localhost:40664 | jaikoz   | Sleep   |    20 |       | NULL             |
| 127755 | paul | localhost:40665 | jaikoz   | Sleep   |     8 |       | NULL             |
| 127756 | paul | localhost:40666 | jaikoz   | Sleep   |    25 |       | NULL             |
| 128444 | paul | localhost:41250 | jaikoz   | Sleep   |    14 |       | NULL             |
| 128445 | paul | localhost:41251 | jaikoz   | Sleep   |    10 |       | NULL             |
| 134807 | paul | localhost:56829 | jaikoz   | Sleep   |   226 |       | NULL             |
| 134849 | paul | localhost:38795 | songkong | Sleep   |   475 |       | NULL             |
| 143552 | paul | localhost:35811 | jaikoz   | Sleep   | 19338 |       | NULL             |
| 145211 | paul | localhost       | jaikoz   | Query   |     0 | NULL  | show processlist |
+--------+------+-----------------+----------+---------+-------+-------+------------------+
14 rows in set (0.00 sec)

也许 Jaikoz 进程不应该那么多?

我该如何解决这个问题?

已编辑

与其他人交谈,因为只有来自商店 Web 应用程序的连接失败,并且只有在进行购买时才会执行任何操作,目前一天只有几次,听起来连接超时了通过 MySql 本身而不告诉 jdbc 池,所以当尝试通过池使用连接时,我们得到错误。

我将 testWhileIdle="true" 添加到我的 context.xml 并删除了 autoreconnect=true 希望这会在 mysql 放弃之前从池中删除连接。

不幸的是,仍然偶尔失败,但现在给出了稍微不同的错误消息

JDBC begin transaction failed
  • 关闭连接池。
  • 关闭 auto-reconnect
  • 确保您的代码捕获事务错误,并在必要时重播它们——尤其是在出现死锁的情况下。

这些问题往往与金融交易的完整性有关。

如果这些不能解决问题,请提供

  • 每秒查询数
  • 显示像“%timeout”这样的变量;`
  • 交易样本(SQL,请不要Java)
  • SHOW CREATE TABLE

至于PROCESSLIST...

  • 我看到一个连接(可能是池化的)在 5 秒前执行了一些 SQL。
  • 我看到一个连接(可能是共用的)在 19338 秒前(超过 5 小时)没有做任何事情。
  • 我猜想您在过去 5 小时内需要的同时 个连接不超过 12 个。
  • 列表看起来 "normal"。

关键是我需要提供 validationQuery 才能使 testForIdle 完成的验证工作,从那以后就没有问题了。

 <Context path="/store" privileged="true">
            <Resource name="jdbc/myapp" auth="Container" type="javax.sql.DataSource"
                      maxActive="10" maxIdle="10" 
    testWhileIdle="true" validationQuery="select 1" validationQueryTimeout="5"
                      username="usrnm" password="pwd" 
driverClassName="com.mysql.jdbc.Driver" testOnBorrow="true"
                      url="jdbc:mysql://localhost:3306/myapp"/>

        </Context>