【问题标题】:InnoDB transactions - doesn't workInnoDB 事务 - 不起作用
【发布时间】:2014-04-25 13:42:55
【问题描述】:

我想尝试一下交易以及它们的实际运作方式。所以我决定写两个脚本来测试事务的主要功能(处理对数据库的同时访问)

我已经在 stackOverflow 上问了一个问题,以下是该问题的编辑。但是我再次阅读了规则,我认为将其发布在我原来的问题下可能是错误的,因为它是不同的。所以我提出了一个新问题:

我的代码(并且数据库表设置为 InnoDB):

在 page1.php 上:

$db->query("START TRANSACTION;");

$db->query("SET AUTOCOMMIT = 0;");
try {
$i = 0;
while ($i <= 120000000) {
    $i++;
}
var_dump($db->query("INSERT INTO test VALUES (NULL, 'testvalue')"));
$db->query("COMMIT;");
}
catch (Exception $e) {
$db->query("ROLLBACK;");
echo $e->getMessage();
}

query-方法有效。它只是查询字符串。 while-loop 只适合我。我需要一点时间去另一个浏览器选项卡来加载 page2.php:

$db->query("START TRANSACTION;");
$db->query("SET AUTOCOMMIT = 0;");
try {
    // outputs an array with the data
    var_dump($db->query("SELECT * FROM test", "assoc"));
    $db->query("COMMIT;");
}
catch (Exception $e) {
    $db->query("ROLLBACK");
    echo $e->getMessage();
}

使用SELECT,我得到了一个数组,其中包含数据库表中的所有值,起初它是空的。

现在我打开了page1.php,它将新数据插入database。但首先它通过循环运行,大约需要 3-4 秒。同时,我打开了page2.php

据我了解,page2.php 应该等待 page1.php 完成其transaction??但它只是像往常一样加载并输出一个空数组。

当我在 page1.php 完成加载后刷新 page2.php 时,我得到了包含新数据的正确输出。

我的错误在哪里?我不太明白。

编辑:这是我尝试过的另一个:

page1.php

$db->query("SET AUTOCOMMIT = 0;");
$db->query("START TRANSACTION;");
try {

    //print_r($db->query("DELETE FROM test;", "affected"));
    $i = 200;
    while ($i <= 700) {
        var_dump($db->query("INSERT INTO test VALUES ({$i}, 'testvaluetestvaluetestvaluetestvaluetestvalue')"));
        $i++;
    }

    $db->query("COMMIT;");
}
catch (Exception $e) {
    $db->query("ROLLBACK;");
    echo $e->getMessage();
}

page2.php

$db->query("SET AUTOCOMMIT = 0;");
$db->query("START TRANSACTION;");

try {
    var_dump($db->query("SELECT * FROM test", "assoc"));
    $db->query("COMMIT;");
}
catch (Exception $e) {
    $db->query("ROLLBACK");
    echo $e->getMessage();
}

虽然 page1.php 没有完成,但第 2 页应该输出 nothing,但它会输出前 70 行(取决于我重新加载的速度)

【问题讨论】:

  • 第 2 页不会等待第 1 页,否则您可能会遇到一些严重的性能问题:它会在请求的位置读取数据库,但应该只读取未被修改的数据第 1 页 .... 即在任何第 1 页插入/更新/删除之前的数据库状态
  • ACID 可能会让您了解交易的全部内容
  • 哦,好的。但我也尝试了另一件事。在第 1 页上,我在数据库中插入了 500 行,这需要几秒钟。同时我打开第 2 页,它确实输出了前 70 行,这些行正在由第 1 页添加。但我不明白为什么。因为autocommit 被禁用,所以它应该(如你所说)仅在查询所有插入之后应用这些插入。也许我在我的问题中发布了这段代码。也许有一个错误。

标签: php sql transactions innodb


【解决方案1】:

事务尽量避免锁定表/行以提高并发性。这是一件好事。

它们的作用是确保一组 sql 语句都作为一个原子单元执行。

意思是如果发生错误,事务中的所有查询都会回滚。

可以通过隔离模式控制锁定的严格/激进程度,更多信息请参见 mysql 文档。

所以听起来你误解了他们的目的,这不是信号量机制。

【讨论】:

  • 很好的答案,但请不要在这里全小写。我们有很多编辑在提高问答质量,我们不想给他们额外的工作:)
【解决方案2】:

这是事务的预期行为...您期望的是悲观锁定机制,但是每个关系数据库都使用乐观锁定和事务隔离来使事情变得更快。

您可以在pgsql manual 中了解更多信息。我知道你的问题是关于 mysql 的,但这并不重要,因为它是关于并发控制概念的:ACID 属性和事务隔离级别等......

【讨论】:

    猜你喜欢
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    相关资源
    最近更新 更多