cli执行脚本时出现(2006 MySQL server has gone away) 问题处理

最近有同事问我,有个cli运行的处理脚本经常没执行完就退出了,导致日志表里显示脚本运行状态一直显示在执行中。

了解到他的逻辑如下:

程序开始时建立两个数据库连接A和B(因为业务数据表和日志表在两个数据库中),连接A用来保存抓取的业务数据,连接B用来保存脚本运行的状态。当抓取的数据保存完后,用连接B将日志表中的脚本运行状态改为已完成。

听到这个问题就觉得可能是数据库连接断开引起的,因为mysql服务器端在连接闲置时间(wait_timeout)达到设定值后,就会释放掉该连接,开始排查吧。

问题排查过程:

//开始执行脚本
php /path/test.php 

//查看PHP脚本进程ID
ps -ef|grep "test.php"

//用strace查看进程执行过程 
strace -tt -s 512 -p 1111

//手动关闭mysql连接,模拟连接断开的场景

mysql -uroot -p123 -h127.0.0.1

show processlist;

kill  进程ID;

 

发现有两个问题

1、在用CURL请求外部接口时,如果请求失败抛异常,但业务代码里没有对异常进行处理,导致请求接口超时或其它错误时直接退出执行。

        $errno = curl_errno($ch);
        if ($errno)
        {
            curl_close($ch);
            throw new Exception($errno,0);
        }

这明显是程序员经验不够,忘记了处理异常。处理方法就是在业务代码里用CURL请求接口时,使用try  catch去捕获异常进行处理。

2、当mysql连接被关闭后,再去做select或insert/update操作时,会异常退出(2006 :MySQL server has gone away)。

这里对数据操作类mysqli.class.php做了一些修改,增加了失败错误码为2006时重试机制

          if ($this->_linkID->errno == 2006 || $this->_linkID->errno == 2013){
                $this->close();
                $this->initConnect(true);
                $result =   $this->_linkID->query($str);
                if(false !== $result){
                    $this->numRows = $this->_linkID->affected_rows;
                    $this->lastInsID = $this->_linkID->insert_id;
                    return $this->numRows;
                }
            }

 

你可能感兴趣的:(数据库,php)