2010-01-05 59 views
1

我试图充分理解事务的概念。因此,下面的问题......(当然新手,所以不要笑:D)PHP中的SQL服务器事务

我已经在PHP(使用微软的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)它可能是在事务开始和实际提交之间,来自另一个连接的另一个查询改变了匹配的行(一个< 10)?这意味着我期望的结果根据$结果将不同于数据库中的实际更改。或者是(a)事务发生在数据库的内存中副本上(不受其他连接的内部查询影响),或(b)自事务开始以来获得的锁定是已经为来自其他连接的其他查询采取行动?

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

+0

$ conn'中的连接在提交后仍然打开吗?如果没有,也许这就是'$ result2'为空的原因。 (它试图使用一个关闭的连接)。 – 2010-01-05 17:00:24

回答

1

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

+0

是的,你让我在那里:它的逻辑$ result2返回空。 关于我的第二个问题:你是否同意2b? – chrizzler 2010-01-06 09:57:00

+0

不可以。使用事务的要点是使两个或多个数据库操作成为原子,所以在启动和提交之间不应该有任何外部更改 – Thilo 2010-01-12 15:58:15

0

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

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