我想尝试交易以及它们如何实际运作。所以我决定编写两个脚本来测试事务的主要功能(处理对数据库的同时访问)
我已经在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
- 循环适合我。我需要一点时间去其他浏览器选项卡加载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行(取决于我重新加载的速度)
答案 0 :(得分:1)
事务尝试尽可能避免锁定表/行以提高并发性。这是一件好事。
它们的用途是确保一组sql语句都作为原子单元执行。
表示如果发生错误,则回滚事务中的所有查询。
可以使用隔离模式控制锁定的严格/积极性,在mysql文档中有更多信息。
所以听起来你误解了它的目的,不是信号量机制。
答案 1 :(得分:0)
这是事务的预期行为......您期望的是一种悲观的锁定机制,但每个关系数据库都使用乐观锁定和事务隔离来使事情更快。
您可以在pgsql manual中详细了解相关信息。我知道你的问题是关于mysql的,但它并不重要,因为它涉及并发控制概念:ACID属性和事务隔离级别等......