【问题标题】:How to execute multiply queries using PHP's prepared statemens with MySQL's transaction?如何使用 PHP 的预处理语句和 MySQL 事务执行多个查询?
【发布时间】:2016-04-13 14:04:42
【问题描述】:

我需要使用 PHP 的预处理语句和 MySQL 的事务来执行 2 个或更多不完全相同的查询(本例中为 INSERT's。)。因此,如果我有 2 个 INSERT 语句,我希望它们都执行,或者都不执行。

我想将此示例 MySQL 事务转换为 PHP 代码:

START TRANSACTION;
     INSERT INTO `file` (`name`, `mime_type`, `size`, `comment`) VALUES ('file.png', 'image/png', '1024', 'My comment');
     INSERT INTO `complementary_file` (`file_id`, `user_id`) VALUES (LAST_INSERT_ID(), '1');
COMMIT;  

我正在处理的 PHP 代码:

mysqli_autocommit($connection, FALSE);
if ($stmtFile = mysqli_prepare($connection, "INSERT INTO `file` (`name`, `mime_type`, `size`, `comment`) VALUES (?, ?, ?, ?)")) {
    mysqli_stmt_bind_param($stmtFile, 'ssis', $name, $mime_type, $size, $comment);
    if (mysqli_stmt_execute($stmtFile)) {
        if ($stmtComplementaryFile = mysqli_prepare($connection, "INSERT INTO `complementary_file` (`file_id`, `user_id`) VALUES (?, ?)")) {
            mysqli_stmt_bind_param($stmtComplementaryFile, 'ii', mysqli_insert_id($connection), $user_id);
            mysqli_stmt_execute($stmtComplementaryFile);
        }
    } else {
        mysqli_rollback($connection);
    }
}
mysqli_commit($connection);  

上面的 PHP 代码可以运行,但是如果我有更多关键语句要执行怎么办?有没有很好的方法可以同时使用 PHP 的准备好的语句 事务执行语句?

请注意,对于$stmtComplementaryFile,我必须有一个mysqli_insert_id() 值。另请注意,我没有在这段代码中使用 PDO——如果建议是 MySQLi,我将不胜感激。谢谢。

【问题讨论】:

  • 在准备之前你不需要运行mysqli_begin_transaction 吗? (注意:这不是回答你的问题,我只是想知道,因为你正在翻译一个事务,但没有在 PHP 中使用事务)。
  • 我在mysqli_autocommit($connection, FALSE); 之后添加了mysqli_begin_transaction($connection, MYSQLI_TRANS_START_READ_ONLY);,现在INSERT 的两个都不起作用。
  • 我猜它是一个只读事务时它不会工作。
  • 糟糕!将其更改为MYSQLI_TRANS_START_READ_WRITE INSERTs 都有效。
  • 看起来问题中的代码已经过编辑以包含答案,而这个问题仍然是开放的,没有答案。如果原始问题的答案是......“添加对 mysqli_begin_transaction() 的调用”,那么应该将其作为问题的 answer 发布,并且应该接受答案。现在看来,这个问题似乎仍然没有答案。 (糟糕的形式。)

标签: php mysql mysqli transactions prepared-statement


【解决方案1】:

以下SQL:

START TRANSACTION;
     INSERT INTO `file` (`name`, `mime_type`, `size`, `comment`) VALUES ('file.png', 'image/png', '1024', 'My comment');
     INSERT INTO `complementary_file` (`file_id`, `user_id`) VALUES (LAST_INSERT_ID(), '1');
COMMIT;  

可以转换成PHP(使用prepared statements)如下:

mysqli_begin_transaction($connection, MYSQLI_TRANS_START_READ_WRITE);
if ($stmtFile = mysqli_prepare($connection, "INSERT INTO `file` (`name`, `mime_type`, `size`, `comment`) VALUES (?, ?, ?, ?)")) {
    mysqli_stmt_bind_param($stmtFile, 'ssis', $name, $mime_type, $size, $comment);
    if (mysqli_stmt_execute($stmtFile)) {
        if ($stmtComplementaryFile = mysqli_prepare($connection, "INSERT INTO `complementary_file` (`file_id`, `user_id`) VALUES (?, ?)")) {
            mysqli_stmt_bind_param($stmtComplementaryFile, 'ii', mysqli_insert_id($connection), $user_id);
            mysqli_stmt_execute($stmtComplementaryFile);
        }
    } else {
        mysqli_rollback($connection);
    }
}
mysqli_commit($connection);  

一般来说,这两个语句是等价的,但是最好知道什么是事务,什么不是事务。

事务是一种机制,可确保批量操作以原子方式执行,并且仅当所有操作都成功时,它们的结果才会反映在数据库中。它确保atomicity 的操作。

事务不是在表上实现互斥锁的机制。如果需要锁定表,则需要使用 LOCK TABLES [READ|WRITE]。等效地在 PHP 中,这是通过执行以下操作来实现的:

mysqli_query($connection, "LOCK TABLES tableName as TableAlias [read|write]");

紧随其后

mysqli_query($connection, "UNLOCK TABLES"); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    相关资源
    最近更新 更多