【问题标题】:PDOException with DROP TABLE IF EXISTSPDOException with DROP TABLE IF EXISTS
【发布时间】:2013-01-02 16:01:34
【问题描述】:

我正在使用 PDO 调用以 DROP TABLE IF EXISTS 开头的存储过程。我随机得到 PDOException 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'historygr.reached' doesn't exist' 更烦人的是它会从告诉我到抛出异常说表已经存在,在几秒钟之内,似乎来自同一个连接。

我自己无法触发错误,但我会收到错误通知。

这是错误源自的 PHP:

$dbh = PDODB::getInstance();
$stmt = $dbh->query("CALL ListReached(".$this->item_id.")"); // <-- ERROR
$items = $stmt->fetchAll();

这是 MySQL 过程定义:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `ListReached`( IN root INT)
BEGIN
    DECLARE rows SMALLINT DEFAULT 0;

    DROP TABLE IF EXISTS reached;
    CREATE TABLE reached(
    node_id INT PRIMARY KEY
    ) ENGINE=HEAP;

    INSERT INTO reached VALUES (root);
    SET rows = ROW_COUNT();

    WHILE rows > 0 DO
    INSERT IGNORE INTO reached
        SELECT DISTINCT child_id 
        FROM related_item AS r
        INNER JOIN reached AS p ON r.parent_id = p.node_id;
    SET rows = ROW_COUNT();

    INSERT IGNORE INTO reached
        SELECT DISTINCT parent_id
        FROM related_item AS r
        INNER JOIN reached AS p ON r.child_id = p.node_id;
    SET rows = rows + ROW_COUNT();
    END WHILE;

    DELETE FROM reached WHERE node_id = root;

    SELECT * FROM reached;
    DROP TABLE reached;

END

【问题讨论】:

    标签: php mysql pdo


    【解决方案1】:

    您正在达到比赛条件。

    如果两个连接都在执行同一个脚本,它们会同时创建和删除同一个表,从而导致冲突。

    考虑使用临时表,而不是在事务中创建和删除真实表。

    http://dev.mysql.com/doc/refman/5.1/en/create-table.html

    您可以在创建表时使用 TEMPORARY 关键字。 TEMPORARY 表仅对当前连接可见,并在连接关闭时自动删除。这意味着两个不同的连接可以使用相同的临时表名称,而不会相互冲突或与现有的同名非临时表冲突。 (在删除临时表之前,现有表是隐藏的。)要创建临时表,您必须具有 CREATE TEMPORARY TABLES 权限。

    编辑

    正如 cmets 中提到的,查询多次引用表。

    另一种方法是在过程中使用锁:http://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_get-lock

    【讨论】:

    • 很遗憾不能使用临时表,因为您不能在查询中多次引用它们,这就是过程的功能
    • 是的,您需要创建临时表的副本以多次引用它(每个引用 n-1 个副本),或者将您的查询更改为不多次引用临时表表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2020-05-11
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多