Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当使用PHP脚本更新具有打开/挂起事务的DB表时,如何避免无限期阻塞?_Php_Apache_Database - Fatal编程技术网

当使用PHP脚本更新具有打开/挂起事务的DB表时,如何避免无限期阻塞?

当使用PHP脚本更新具有打开/挂起事务的DB表时,如何避免无限期阻塞?,php,apache,database,Php,Apache,Database,我发现,如果我通过SQLplus修改表X而不提交更改,那么如果我的web应用程序(在ModPHP模式下作为Apache下的PHP脚本运行)尝试提交对表X的更改,它将无限期阻止,直到我通过SQLplus提交更改为止 这种行为是正确的,但我想要的是一种干净/可靠/简单的方法,使我的web应用程序在N秒后超时,并发出HTTP 409错误,而不是无限期地阻塞 我的第一个想法是使用带有信号处理器的pcntl_报警(N)在N秒后捕捉信号。但我发现pcntl_*函数通常在编译时从ModPHP Apache模块

我发现,如果我通过SQLplus修改表X而不提交更改,那么如果我的web应用程序(在ModPHP模式下作为Apache下的PHP脚本运行)尝试提交对表X的更改,它将无限期阻止,直到我通过SQLplus提交更改为止

这种行为是正确的,但我想要的是一种干净/可靠/简单的方法,使我的web应用程序在N秒后超时,并发出HTTP 409错误,而不是无限期地阻塞

我的第一个想法是使用带有信号处理器的pcntl_报警(N)在N秒后捕捉信号。但我发现pcntl_*函数通常在编译时从ModPHP Apache模块中删除,大概是为了避免弄乱根Apache进程本身用来控制其子进程的信号。也许通过ModPHP运行的PHP脚本处理自己的SIGARLMs应该是有害的,但我现在不想和我的Ops团队打这场仗,所以我不得不拒绝这种方法

我的第二个想法是,每当我的应用程序需要修改表X时,分叉/启动一个子进程,并让父进程轮询子进程(可能通过管道上的select()),直到操作完成(成功)或N秒过去(超时+失败)

第二种方法会奏效,但我觉得它丑陋、复杂、脆弱


考虑到PHP版本5.2.11和Apache版本1.3.41(在Linux 2.6.9上)的限制,有人知道更好的方法吗?

我认为在这种情况下,我会尝试直接控制查询超时。最好的方法是使用PHP的MySQLi模块,而不是MySQL模块,因为这样您就可以访问该函数

使用mysqli::options,可以根据每个连接将查询超时值设置为所需的任何值。一旦它超时,您可以控制代码中的错误,作为正常流程的一部分

如果您不能使用MySQLi(或者您没有使用MySQL 5),您可以始终直接在MySQL选项中设置此值,但这当然会对您的应用程序产生更大的影响

编辑

作为对你评论的回应,我认为这可能行不通。我刚想到一件很笨重的东西,但也许能让你过去

该函数可以对PHP脚本的执行设置总时间限制,如果达到该限制,将触发PHP致命错误。但是,当您调用它时,计时器将重置为零。。。PHP致命错误可以处理

您可以编写自己的错误处理函数,在执行问题查询之前,通过将其替换为可用。立即调用
set\u time\u limit()
,并运行查询。如果超过时间限制,将触发致命错误,并转到错误处理函数。你可以从那里开始

如果它没有被触发,您可以在查询之后再次调用
set\u time\u limit()
重置计时器,然后使用将默认错误处理函数调回原位


正如我所说的,笨重,但也许可以工作?

不幸的是,在ModPHP+Apache下运行时,PHP似乎不允许使用pcntl_*()函数。在Linux上运行时,PHP本身为设置脚本超时提供的功能只适用于脚本本身所花费的时间,而不是等待阻塞的DB查询所花费的时间

因此,您必须采取一般策略,启动一个新进程(我们不能调用pcntl_fork())来“执行可能会阻塞的操作”,然后让父进程轮询连接并在N秒后放弃。一种方法是使用proc_open(),将PHP端管道设置为非阻塞(通过stream_set_blocking())和stream_select()轮询循环,该循环在一定时间后中止

这在几个层面上都很烦人。首先,您必须确保正确启动子进程并安全地将所需操作的信息从父进程传递到子进程,然后必须确保轮询逻辑正确处理各种子进程故障情况,然后必须安全地将信息从子进程传递回父进程,最后,您必须在之后正确地清理所有内容(如果父进程持续多次迭代,这一点就变得很重要)。这里的复杂性是如此之大,我敢打赌,几乎任何第一次这样做的人都必须花上数周的时间来修复bug,然后行为才会真正健壮。尽管您可以明确控制轮询频率和错误处理,但您也有启动新流程的相关成本


我承认对于这类问题没有“一刀切”的解决方案,但是每一个用PHP编写web应用程序并与Oracle数据库通信的人都曾一度希望“运行QueryX并在N秒内没有得到响应时抛出异常”。因此,让我感到可笑的是,每个想要这种行为的人都必须实现上述整个系统(或者找到其他人已经实现了)。

在我的例子中,我是通过一个轻量级数据库访问层从PHP与Oracle DB对话,该层直接调用oci8驱动程序。我一直希望有一个通用的(DB不可知)解决方案,但也许你是对的,我需要深入研究一下客户端。我没有为oci_connect()函数记录连接超时参数。有人在PHP网站上发布了一个解决方案,其中涉及调整sqlnet.ora文件(),但我不想这样做,因为我的各种连接和查询有不同的要求。啊,是的,对不起……在处理PHP问题时,我总是假设MySQL。如果您不能基于每个连接修改数据库连接时间,那么您可能会遇到类似set_time_limit的问题。事实上我会的