在使用php原生api连接mysql数据库的时候往往需要建立与本地mysql的多个连接,这个时候,mysql会为你多次连接返回同样的文件描述符。这本来是php对mysql连接的一种优化,对于同一台机器的不同数据库操作,提供统一的连接,避免大量的新连接,影响通讯效率。但如果不注意控制会出现问题。
问题:
如果在程序开始部分,对同一台机器的数据库建立了多个连接,例如使用mysql_connect 函数连接了本地数据库a与b,返回的都是资源描述符9(mysql_connect 的返回值)此后并没有任何查询操作,mysql会对这种sleep连接进行断开(可以设置wait_timeout来控制断开的等待时间),这个时候,对资源描述符9的连接已经断开,当你再要查询的时候,mysql会返回gone away的错误,errno代码为2600,此时你需要重新连接mysql,为了让php真正重新连接,而不是返回已经存在的断开的9号描述符,需要先调用mysql_close函数,结束已经断开的9号连接,然后再次调用mysql_connect进行连接。
此时问题出现了,调用mysql_close,打印mysql_close信息,返回的是true,说明关成功。再次mysql_connect后系统返回的仍旧是刚才断开的9号描述符,查询还会显示mysql gone away。正常情况下当调用mysql_close后,再次连接,系统会分配一个新的资源符。说明由于开始的时候多次连接返回相同的描述符对mysql_close调用产生了影响,没有真正断开资源描述符为9的连接。
原理猜想:
程序开始部分多次连接,php返回相同的资源描述符,同时维护一个描述符的引用计数,由于连接两次,引用计数为2,当调用mysql_close的时候,第一次调用会对引用计数-1,这个时候系统知道还有一个连接使用该资源描述符,所以不会真正断开连接,虽然这个连接由于超时了,已经不能使用。只有再次调用mysql_close的时候,引用计数再次-1,这次引用计数为0,mysql_close函数才会真正断开连接,再次使用mysql_connect函数的时候才会建立新的连接。
解决方法:
在调用mysql_connect时候给定最后一个参数 $new_link 为true,这样对相同参数调用返回不同的描述符,再次查询时候,如果发现gone away,调用mysql_close即可关闭这个连接,然后新建连接即可。
猜想:
在使用mysqli的时候好像没有出现过这种问题,因为在连接时候直接选择了不同的数据库,无需再单独选择数据库,这个时候系统返回的描述符可能因为连接的库不同直接就返回不同描述符,不会出现上面这种现象。这个待证实。
来源:http://hi.baidu.com/johntech/blog/item/d7d9390a8e232add63d986ed.html
问题:
如果在程序开始部分,对同一台机器的数据库建立了多个连接,例如使用mysql_connect 函数连接了本地数据库a与b,返回的都是资源描述符9(mysql_connect 的返回值)此后并没有任何查询操作,mysql会对这种sleep连接进行断开(可以设置wait_timeout来控制断开的等待时间),这个时候,对资源描述符9的连接已经断开,当你再要查询的时候,mysql会返回gone away的错误,errno代码为2600,此时你需要重新连接mysql,为了让php真正重新连接,而不是返回已经存在的断开的9号描述符,需要先调用mysql_close函数,结束已经断开的9号连接,然后再次调用mysql_connect进行连接。
此时问题出现了,调用mysql_close,打印mysql_close信息,返回的是true,说明关成功。再次mysql_connect后系统返回的仍旧是刚才断开的9号描述符,查询还会显示mysql gone away。正常情况下当调用mysql_close后,再次连接,系统会分配一个新的资源符。说明由于开始的时候多次连接返回相同的描述符对mysql_close调用产生了影响,没有真正断开资源描述符为9的连接。
原理猜想:
程序开始部分多次连接,php返回相同的资源描述符,同时维护一个描述符的引用计数,由于连接两次,引用计数为2,当调用mysql_close的时候,第一次调用会对引用计数-1,这个时候系统知道还有一个连接使用该资源描述符,所以不会真正断开连接,虽然这个连接由于超时了,已经不能使用。只有再次调用mysql_close的时候,引用计数再次-1,这次引用计数为0,mysql_close函数才会真正断开连接,再次使用mysql_connect函数的时候才会建立新的连接。
解决方法:
在调用mysql_connect时候给定最后一个参数 $new_link 为true,这样对相同参数调用返回不同的描述符,再次查询时候,如果发现gone away,调用mysql_close即可关闭这个连接,然后新建连接即可。
猜想:
在使用mysqli的时候好像没有出现过这种问题,因为在连接时候直接选择了不同的数据库,无需再单独选择数据库,这个时候系统返回的描述符可能因为连接的库不同直接就返回不同描述符,不会出现上面这种现象。这个待证实。
来源:http://hi.baidu.com/johntech/blog/item/d7d9390a8e232add63d986ed.html
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/3349/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
评论列表