PHP';当无法访问服务器时,s PDO将忽略MySQL的ATTR_TIMEOUT选项

PHP';当无法访问服务器时,s PDO将忽略MySQL的ATTR_TIMEOUT选项,php,mysql,pdo,connection,Php,Mysql,Pdo,Connection,我正在测试的场景中,mysql服务器无法通过输入随机IP来尝试连接。我使用PDO::ATTR_TIMEOUT=>1将PDO的选项设置为一秒钟后超时。但是,抛出异常仍然需要30秒。我猜这个超时只适用于实际的mysql连接时间,而不适用于运行mysql的服务器 我需要更改哪些PHP选项来暂停与mysql服务器的连接?在PHP.ini上,可以更新此配置变量: mysql.connect_timeout = 1 PDO::ATTR_TIMEOUT:以秒为单位指定超时持续时间不是全部 驱动程序支持此选项

我正在测试的场景中,mysql服务器无法通过输入随机IP来尝试连接。我使用
PDO::ATTR_TIMEOUT=>1
将PDO的选项设置为一秒钟后超时。但是,抛出异常仍然需要30秒。我猜这个超时只适用于实际的mysql连接时间,而不适用于运行mysql的服务器


我需要更改哪些PHP选项来暂停与mysql服务器的连接?

PHP.ini
上,可以更新此配置变量:

mysql.connect_timeout = 1
PDO::ATTR_TIMEOUT:以秒为单位指定超时持续时间不是全部 驱动程序支持此选项,其含义可能因驱动程序而异 驱动程序。例如,sqlite将在之前等待此时间值 放弃获取可写锁,但其他驱动程序可能会 将其解释为连接或读取超时间隔

文档明确指出,这可能并不意味着连接超时时间间隔,或者有时驱动程序不支持它

$host = '192.168.1.36'; $dbname = 'test'; $username = 'test'; $password = ''; $start = time(); try { $db = new PDO( "mysql:host=$host;dbname=$dbname", $username, $password, array( PDO::ATTR_TIMEOUT => 1, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ) ); } catch(Exception $e) { echo time() - $start; echo "\n"; echo $e->getMessage(); } $host='192.168.1.36'; $dbname='test'; $username='test'; $password=''; $start=time(); 试一试{ $db=新PDO( “mysql:host=$host;dbname=$dbname”, $username, $password, 排列( PDO::ATTR_TIMEOUT=>1, PDO::ATTR_ERRMODE=>PDO::ERRMODE_异常 ) ); }捕获(例外$e){ 回声时间()-$start; 回音“\n”; echo$e->getMessage(); } 这个代码片段应该可以解决您的问题

mysqli、mysqlnd、pdo-mysql的区别:

  • (已弃用)mysqlnd表示msyql本机驱动程序,其函数是过程性的
  • mysql目录的mysqli对象形式
  • pdo mysql是pdo数据库抽象插件,支持连接到mysql数据库
只要把

ini_set("default_socket_timeout", 2);
在PDO()连接字符串之前

(在Windows上测试,在Linux上也可以。)


为什么?

通过手册了解这一点:

mysqlnd驱动程序对底层连接使用套接字,要设置超时,您需要使用套接字(流)超时函数。(参考号:)

使用mysqlnd意味着使用PHP流进行底层连接。对于mysqlnd,应该参考PHP流文档(streams),了解超时设置等详细信息,而不是MySQL客户机库的文档


如果您想要更多的控制,那么您可能能够更具体地控制实际的套接字:我没有测试过它,因为它只是unix。要设置mysqlnd使用的套接字,可以使用ini设置指定套接字(Ref:)

如果根据mysqlnd编译PDO_MYSQL,则可以通过PDO_MYSQL.default_socket设置设置默认套接字

看看那个场景

然后,您可以使用


但是设置默认值并在完成后重置可能更容易…

将选项传递给PDO构造函数:


对我来说,如果你把这个选项放在PDO的构造函数中,它就会工作。并忽略php.ini中的任何设置

$options = array(PDO::ATTR_TIMEOUT] => 1);//must be in the constructor
$db = new DB($dsn, $username, $password, $options);
因为我们在这里测试初始连接,所以在打开连接时,它需要有这个选项是有意义的。因此,对于初始连接之后的任何查询,下面都应该适用

$db = new DB($dsn, $username, $password, $options);
$db->setAttribute(PDO::ATTR_TIMEOUT, 2);

这不起作用。我将
ini\u设置为('mysql.connect\u timeout',1)连接之前。几个问题-如何设置
PDO::ATTR_TIMEOUT
,即连接字符串是什么?您是使用MySQLnd还是常规的mysql驱动程序?您的PHP和mysql驱动程序是什么版本的?您应该发布连接到mysql数据库所用的完整代码。启动赏金和不添加评论者请求的其他信息是没有意义的。@MatteoSp很抱歉,启动赏金后我变得非常忙。至于连接字符串,它几乎是nobody0day发布的内容。这是默认的Laravel连接器+超时,因此它使用异常作为错误模式。Linux上的MySQL驱动程序肯定不是这种情况-例如,如果您将
PDO::ATTR\u timeout
设置为7,并且
strace
脚本建立连接,您将看到
connect(3,{sa\u family=AF\u INET,sin\u port=htons(3306),sin_addr=inet_addr(“10.0.0.0”)},16)=-1 EINPROGRESS(操作正在进行)轮询([{fd=3,events=POLLIN | POLLPRI}],1700
我使用的是mysqlnd,它应该支持它。您对本机驱动程序的评论非常错误。它非常不受欢迎。这个库提供了比原始mySQL驱动程序多得多的控制,应该使用它(例如,整数作为整数返回,而不是字符串,可以使用本机准备的语句)。旧的mySQL()函数被弃用:这根本没有连接到本机驱动程序。很有趣。如果我将
默认\u socket\u timeout
设置为1秒,但不使用PDO连接超时选项,一秒钟后它不应该仍然超时吗?我只是问,因为我不确定发生了什么,但PDO超时突然开始为我工作,though同样的问题仍然存在于memcached连接中。这是正确的。Memcache在connect函数中有一个超时作为参数。因此,使用mysqlnd的默认套接字超时,memcachedPlease的参数在您的答案中包含实际的解决方案。链接不再工作,因为repo已以某种方式更改。