mariadb 长链接时间限制导致队列消费进程崩溃

项目是一个数据同步项目,线下Android客户端把本地sqllite数据提交到云端队列,php做守护进程消费队列,以同步数据。初测没有问题,可是时不时出现诡异的崩溃,因为设置了错误邮件报警,发现错误代码如下:

PHP Warning 'yii\base\ErrorException' with message 'Error while sending QUERY packet. PID=45905'

in /home/muffycat_takeout/vendor/yiisoft/yii2/db/Transaction.php:121

Stack trace:

#0 [internal function]: yii\base\ErrorHandler->handleError(2, 'Error while sen...', '/home/muffycat_...', 121, Array)

#1 /home/muffycat_takeout/vendor/yiisoft/yii2/db/Transaction.php(121): PDO->beginTransaction()

#2 /home/muffycat_takeout/vendor/yiisoft/yii2/db/Connection.php(663): yii\db\Transaction->begin(NULL)

#3 /home/muffycat_takeout/takeoutapi/models/DishesModel.php(108): yii\db\Connection->beginTransaction()

#4 /home/muffycat_takeout/takeoutapi/service/meituan/DishService.php(76): takeoutapi\models\DishesModel::addDisheMapping(Array, '234', 1)

#5 /home/muffycat_takeout/console/controllers/DishController.php(49): takeoutapi\service\meituan\DishService->sync()

#6 [internal function]: console\controllers\DishController->actionSync()

#7 /home/muffycat_takeout/vendor/yiisoft/yii2/base/InlineAction.php(55): call_user_func_array(Array, Array)

#8 /home/muffycat_takeout/vendor/yiisoft/yii2/base/Controller.php(154): yii\base\InlineAction->runWithParams(Array)

#9 /home/muffycat_takeout/vendor/yiisoft/yii2/console/Controller.php(128): yii\base\Controller->runAction('sync', Array)

#10 /home/muffycat_takeout/vendor/yiisoft/yii2/base/Module.php(454): yii\console\Controller->runAction('sync', Array)

#11 /home/muffycat_takeout/vendor/yiisoft/yii2/console/Application.php(180): yii\base\Module->runAction('dish/sync', Array)

#12 /home/muffycat_takeout/vendor/yiisoft/yii2/console/Application.php(147): yii\console\Application->runAction('dish/sync', Array)

#13 /home/muffycat_takeout/vendor/yiisoft/yii2/base/Application.php(375): yii\console\Application->handleRequest(Object(yii\console\Request))

#14 /home/muffycat_takeout/yii(27): yii\base\Application->run()

#15 {main}

然而查看代码,此处的查询sql并没有问题,然后用搜索引擎检索,发现原来mariadb有个一个长链接的超时限制(wait_timeout),默认呢是8个小时,

效果类似于session,如果你在8小时内,有指令不断执行,则不会过期,如果超过8个小时没有任何指令,则mariadb就会断开链接, 可以使用如下命令查看数据库的此参数

show global variables like 'wait_timeout';

想要改变该值做测试,则可以执行如下的指令,该参数的单位为秒(默认为:28800):

set global wait_timeout=300

知道原因后,就可以有办法解决了,这里提供两个方法:

1.即使没有消费队列的需求,也定时的发送一个ping指令给数据库,这样就可以永远不过期,参考的php函数为:mysqli_ping

2.当队列有新数据要消费时,链接数据库,如果没有新数据,进程睡眠期间就主动断开链接,待发现新数据要消费时,重新链接数据库

选择定时ping还是主动重连,应该根据实际业务量来自己衡量,毕竟一直占着茅坑不好,而重链呢又要消耗资源不是?

上一篇:微信小程序open-data获取用户的信息样式设置


下一篇:Wince 6.0获取设备的分辨率 自动设置窗体位置