【问题标题】:SQL server transactions in PHPPHP 中的 SQL 服务器事务
【发布时间】:2010-01-05 16:30:51
【问题描述】:

我正在尝试完全掌握交易的概念。因此以下问题......(当然是新手,所以不要笑:D)

我在 PHP 中设置了一个(简化的)事务(使用 microsoft 的 PHP SQL 驱动程序)。我想获取我要删除的行以便稍后进行一些额外的处理:

sqlsrv_begin_transaction($conn);
$sql = "SELECT * FROM test WITH (XLOCK) WHERE a<10";
$statement = sqlsrv_query($conn,$sql);
$sql = "DELETE FROM test WHERE a<10";
sqlsrv_query($conn,$sql);

$result = get_result_array($statement);
sqlsrv_commit($conn);
$result2 = get_result_array($statement);

1) 我确实在 $result 中得到了预期的结果,但在 $result2 中得到了一个空数组。为什么?

我希望 $result2 中只有一个结果,因为那时事务实际上已经执行了。我猜 $result 中的结果是内存中的一种“临时”结果,而不是实际数据库的结果。

2) 可能是在事务启动和实际提交之间,来自另一个连接的另一个查询更改了匹配的行(a

或者是(a)事务发生在数据库的内存副本中(不受来自其他连接的中间查询的影响),还是(b)自事务开始以来获得的锁已经正在处理来自其他连接的其他查询?

输入此内容后,我期待答案 b....?

【问题讨论】:

  • 提交后$conn中的连接是否仍然打开?如果不是,也许这就是$result2 为空的原因。 (它尝试使用关闭的连接)。

标签: php sql-server transactions locking


【解决方案1】:

我不熟悉 sqlsrv 驱动程序,但如果它与大多数其他 PHP DB 驱动程序一样工作,则 sqlsrv_query 调用的结果不是某种形式的数组的结果集,而是一个 PHP 资源(参见 @987654321 @)。调用 get_result_array 仍会从该资源(在本例中为数据库)检索数据,并且会立即执行此操作。 COMMIT 只影响对数据库的写入,不影响读取,因此您可以立即在 result1 中看到结果。提交事务(即 DELETE)后,下一次调用会正确返回一个空结果集。

【讨论】:

  • 是的,你让我明白了:$result2 返回空是合乎逻辑的。关于我的第二个问题:你同意 2b 吗?
  • 没有。使用事务的全部意义在于使两个或多个数据库操作具有原子性,因此在启动和提交之间不应有任何外部更改
【解决方案2】:

我用一些 mysql 工具(我比较熟悉)对其进行了测试: 1. 当我开始交易并“选择”一条特定记录时,我会直接得到结果。然后从另一个连接中,我删除了相同的记录(使用自动提交),该连接已消失,但对于第一个连接,该记录仍然存在(我再次执行了“选择”而不提交事务)。只有在提交第一个连接的事务并再次执行“选择”之后,记录才会消失。 2. 当我这样做但为第一个“选择”查询获取排他锁时,第二个连接的删除查询将等待,直到第一个连接的事务已提交。

结论:在情况(1)中,对于第一个连接的第二个选择查询,数据库正在返回事务开始时的结果......因此没有考虑其他(写入)在事务开始之后运行的查询。情况(2)正是我原来问题的答案 2b。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-19
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多