dsh12544 2018-08-29 18:35
浏览 48

当结果集抛出SIGNAL时,PDOStatement会“卡住”

I have this sample code:

<?php
$pdo = new PDO(
        'mysql:host=127.0.0.1;dbname=test_sql',
        'root',
        '',
        array(
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

$pdo->query('DROP FUNCTION IF EXISTS tst');
$pdo->query('DROP PROCEDURE IF EXISTS tst2');
$pdo->query('CREATE FUNCTION tst() RETURNS VARCHAR(5) BEGIN RETURN \'x123456\'; END');
$pdo->query('CREATE PROCEDURE tst2() BEGIN SELECT tst(); END');

$st = $pdo->prepare('CALL tst2()');
try {
    $st->execute();
} catch (Throwable $ex) {
    var_dump($ex->getMessage());
    $st->closeCursor(); // same with unset($st)
    var_dump('This is never executed');
}

So it's a PROCEDURE (tst2) that returns a single resultset, in which I call a FUNCTION. But that FUNCTION is (somehow) broken since it returns a data too long for its RETURNS clause.

When I run this file, I get the expected result:

string(93) "SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'tst()' at row 1"

But my problem comes afterward: the PDOStatement seems "broken", and when PHP tries to garbage collect it, or when I try to closeCursor() (so I can do other queries again), or when I try to unset it (for the showcase), then PHP got stuck. It never reaches the other var_dump, it just... got idle for ever?!

I've got this problem on PHP 5.6.35 but also on 7.1.16 and 7.2.4 (all using mysqlnd driver 5.0.5 or 5.0.12). I'm using MySQL 5.7.21 (I did not try on other MySQL versions).

Any clue?


Meanwhile, I've also also tried without using prepared statements (so using $pdo->query) and even using mysqli functions: same issue, PHP is stuck.

But, by changing the content of the procedure so it does not try to return a resultset where the SIGNAL occurs, PHP is no longer stuck. So this will "work" (work = I get the SQL exception in my code and my PHP script is not frozen)

<?php
$pdo = new PDO(
        'mysql:host=127.0.0.1;dbname=test_sql',
        'root',
        '',
        array(
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

$pdo->query('DROP FUNCTION IF EXISTS tst');
$pdo->query('DROP PROCEDURE IF EXISTS tst2');
$pdo->query('CREATE FUNCTION tst() RETURNS VARCHAR(5) BEGIN RETURN \'x123456\'; END');
$pdo->query('CREATE PROCEDURE tst2() BEGIN SET @x := (SELECT tst()); END');

$st = $pdo->prepare('CALL tst2()');
try {
    $st->execute();
} catch (Throwable $ex) {
    var_dump($ex->getMessage());
    $st->closeCursor(); // same with unset($st)
}
var_dump('end');

In fact, it seems that since the SQL error occurs inside a resultset, PDO gets the result set headers from MySQL, then gets the exception and so it stops there, and never "closes" the resultset (statement would be left "opened", awaiting for data that will never come).


Seeing all of these, I've reported the bug to PHP team, because I got the same on mysqli and PDO, with any PDO option, and on a very specific case

https://bugs.php.net/bug.php?id=76815

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 Vue3 大型图片数据拖动排序
    • ¥15 划分vlan后不通了
    • ¥15 GDI处理通道视频时总是带有白色锯齿
    • ¥20 用雷电模拟器安装百达屋apk一直闪退
    • ¥15 算能科技20240506咨询(拒绝大模型回答)
    • ¥15 自适应 AR 模型 参数估计Matlab程序
    • ¥100 角动量包络面如何用MATLAB绘制
    • ¥15 merge函数占用内存过大
    • ¥15 使用EMD去噪处理RML2016数据集时候的原理
    • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大