2010-01-05 61 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。 :)