前言最近在部署本地项目到服务器后遇到了一个奇怪的问题。部署完成后,当时网站可以正常运行,但是第二天访问网站时,会遇到500ServerError。从日志中可以看出MySQL数据库出现异常:翻译如下:最后一个数据包在83827560ms之前成功接收,最后一个数据包在83827560ms之前成功发送。它比服务配置参数wait_timeout的值长。日志中给出的建议如下:译文如下:应该考虑在程序中进行数据库操作前先检查数据库连接的有效性,或者将数据库的autoReconnect属性设置为true来避免这个问题。关于wait_timeout和autoReconnect,我们依次分析介绍!原因分析我们输入mysql的命令行查询超时时间。28800的单位从秒换算成小时,就是8小时。可以看出MySQL的默认设置,当一个连接空闲超过8小时,MySQL就会断开连接。于是发现问题是如果超过这个wait_timeout时间(默认8小时)没有对数据库进行任何操作,MySQL会自动关闭数据库连接以节省资源。第二天确实出现了数据库连接自动断开的问题,也就是一晚上没有对数据库进行任何操作(明显超过8小时)时出现的问题。您可以使用命令showprocesslist;可以查看进程Sleep的Sleep状态,同时可以看到每个进程Sleep了多久:下面介绍解决方法和优化方法!解决方法1、参数autoReconnect表示mysql超时重连后自动断开连接。配置只需要在连接mysql的语句中写上autoReconnect=true即可。jdbc:mysql://127.0.0.1:3306/stock_tweet?autoReconnect=true下面是MySQL官网对autoReconnect的解释:同时可以看到官网不推荐使用这个参数,因为它有一些副作用。具体来说,就是原连接上的事务会被回滚,事务的提交模式会丢失。原始连接持有的所有表锁将被释放。原来连接关联的session会话会丢失,恢复的连接会关联一个新的session会话。原始连接定义的用户变量将丢失。原始连接定义的预编译SQL将丢失。原连接失败,新连接恢复后,MySQL会使用一个新的记录行来存储连接中的性能数据。2、修改配置涉及到两个配置参数interactive_timeout和wait_timeout。wait_timeout指的是mysql在关闭一个非交互连接之前等待的秒数。interactive_time是指mysql在关闭交互式连接之前将等待的秒数。对于交互式连接和非交互式连接,说白了,通过mysql客户端连接数据库是交互式连接,通过jdbc连接数据库是非交互式连接。配置方法:1.会话模式msyql>setglobalwait_timeout=2880000;msyql>设置全局交互超时=2880000;该方法只对当前会话有效。2、修改配置文件,修改/etc/my.cnf文件,在[mysqld]段设置:修改后重启服务器。注意:如果wait_timeout的值设置过大,可能会导致空闲连接过多。如果你的MySQLServer有大量的空闲连接,它们不仅会白白消耗内存,而且如果连接一直累积不断开,最终会达到MySQLServer连接数上限,会报'toomanyconnections'错误。连接池配置因为连接池的配置也会影响到项目与MySQL的连接,所以还需要修改数据库连接池的一些配置。我们以SpringBoot2.0默认的数据库连接池HikariCP为例。主要是以下配置maximum-pool-size:最大连接数,超过这个数,新的数据库访问线程会被阻塞,默认值:10。一个常见的错误是设置太大的值,性能会下降如果连接太多。参考计算公式为:#core_count:CPU个数,effective_spindle_count:硬盘连接数=((core_count*2)+effective_spindle_count)例如:4核1硬盘的服务器,连接数=(4*2)+1=9,凑个整数,10也行。minimum-idle:最小连接数。max-lifetime:最大连接时间,用于设置一个连接在连接池中的存活时间。默认值:30分钟。强烈建议设置的比数据库超时时间小一点(MySQL的wait_timeout参数一般为8小时)。idle-timeout:连接空闲的最长时间,超时后释放。对于其他参数,请参阅:https://github.com/brettwoldridge/HikariCP/wiki/About-Pool-Sizing。
