程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> php mysql事務處理

php mysql事務處理

編輯:MySQL綜合教程

文章簡單的介紹了關於php mysql事務處理的細節以及處理時鎖問題,有需要的朋友可以詳細的看看吧。

事務

BEGIN;
COMMIT;
一段代碼, 修改當前表的兩個字段

先查找出來中,保存到變量裡面,然後相加放到第二個字段的value 裡面

 

 代碼如下 復制代碼 BEGIN;
SELECT value into  @short_destiption  FROM `catalog_product_entity_text` WHERE entity_id = 388 and attribute_id = 62;
SELECT value into  @destiption  FROM `catalog_product_entity_text` WHERE entity_id = 388 and attribute_id = 61;
update catalog_product_entity_text set value = concat( @short_destiption,@destiption)  where  entity_id = 388 and attribute_id ='61';
COMMIT;


務操作,要保證的三個原則性:

原子性(Atomicity):事務是一個原子操作單元,其對數據的修改,要麼全部執行,要麼全都不執行;

一致性(Consistent):在事務開始和完成時,數據都必須保持一致狀態;

隔離性(Isolation):數據庫系統提供一定的隔離機制,保證事務在不受外部並發操作影響的“獨立”環境執行;

持久性(Durable):事務完成之後,它對於數據的修改是永久性的,即使出現系統故障也能夠保持。


於是,我們假設兩個對象A和B

並發對象A 和B

初始狀態數據表查詢結果:


事務開始的順序 A->B

A:開始事務


此刻沒有提交進行commit

在此狀態下B開始了自己的MySQL事務處理:


顯然,在A沒有進行Commit行為的時候,B的事務中的動作無法完成,一直處於事務等待階段,前提是在沒有超出時限,B的動作無法提交。

此刻,如果A進行Commit:


此刻 B的動作中,由等待的


轉變到


說明A完成事務開始解鎖,B事務可以進行,但是此刻B事務沒有提交(Commit)

注意:在這裡我們進行兩個操作,就是兩個對象進行查詢

A的查詢:


依然存在ID為1的這項,原因是B的結果沒提交,但A依舊可以讀該項數據,但是數據為刪除前的數據。

但是,對照B的查詢:


可以知道,B對象結果已經在處理了,只是沒有提交解鎖。

分析可以知道,A讀的是B沒有提交前的結果集合,但B讀的是自己操作的結果集,當B完成提交的時候

此刻,A的結果集合


發現現在狀態下和B的集合一樣,A=B,這也是在理論值的范圍內的。

由此,可以發現其實MySQL鎖的簡單性,當然,也說明當數據庫進行鎖操作時候,只能是寫操作控制,對於讀數據,往往只能訪問到修改前的數據,這部分數據常常被稱為”dirty”或髒數據。在現實中,我們常常是有這樣的需求,當A進行寫操作時候,期望B不要讀數據,是對讀行為的控制。


1.1.       基礎知識和相關概念

1)全部的表類型都可以使用鎖,但是只有InnoDB和BDB才有內置的事務功能。

2)使用begin開始事務,使用commit結束事務,中間可以使用rollback回滾事務。

3)在默認情況下,InnoDB表支持一致讀。

SQL標准中定義了4個隔離級別:read uncommited,read commited,repeatable read,serializable。

       read uncommited即髒讀,一個事務修改了一行,另一個事務也可以讀到該行。

       如果第一個事務執行了回滾,那麼第二個事務讀取的就是從來沒有正式出現過的值。?

       read commited即一致讀,試圖通過只讀取提交的值的方式來解決髒讀的問題,

       但是這又引起了不可重復讀取的問題。

       一個事務執行一個查詢,讀取了大量的數據行。在它結束讀取之前,另一個事務可能完成了對數據行的更改。當第一個事務試圖再次執行同一個查詢,服務器就會返回不同的結果。

       repeatable read即可重復讀,在一個事務對數據行執行讀取或寫入操作時鎖定了這些數據行。

       但是這種方式又引發了幻想讀的問題。

       因為只能鎖定讀取或寫入的行,不能阻止另一個事務插入數據,後期執行同樣的查詢會產生更多的結果。

       serializable模式中,事務被強制為依次執行。這是SQL標准建議的默認行為。

4)如果多個事務更新了同一行,就可以通過回滾其中一個事務來解除死鎖。

5)MySQL允許利用set transaction來設置隔離級別。

6)事務只用於insert和update語句來更新數據表,不能用於對表結構的更改。執行一條更改表結構或begin則會立即提交當前的事務。

7)所有表類型都支持表級鎖,但是MyISAM只支持表級鎖。

8)有兩種類型的表級鎖:讀鎖和寫鎖。

讀鎖是共享鎖,支持並發讀,寫操作被鎖。

寫鎖是獨占鎖,上鎖期間其他線程不能讀表或寫表。

8)如果要支持並發讀寫,建議采用InnoDB表,因為它是采用行級鎖,可以獲得更多的更新性能。

9)很多時候,可以通過經驗來評估什麼樣的鎖對應用程序更合適,不過通常很難說一個鎖比別的更好,這全都要依據應用程序來決定,不同的地方可能需要不同的鎖。當前MySQL已經支持 ISAM, MyISAM, MEMORY (HEAP) 類型表的表級鎖了,BDB 表支持頁級鎖,InnoDB 表支持行級鎖。

10)MySQL的表級鎖都是寫鎖優先,而且是采用排隊機制,這樣不會出現死鎖的情況。對於 InnoDB 和 BDB 存儲引擎來說,是可能產生死鎖的。這是因為 InnoDB 會自動捕獲行鎖,BDB 會在執行 SQL 語句時捕獲頁鎖的,而不是在事務的開始就這麼做。
1.2.       不同鎖的優缺點及選擇

行級鎖的優點及選擇:

1)在很多線程請求不同記錄時減少沖突鎖。

2)事務回滾時減少改變數據。

3)使長時間對單獨的一行記錄加鎖成為可能。

 

行級鎖的缺點:

1)比頁級鎖和表級鎖消耗更多的內存。

2)當在大量表中使用時,比頁級鎖和表級鎖更慢,因為他需要請求更多的所資源。

3)當需要頻繁對大部分數據做 GROUP BY 操作或者需要頻繁掃描整個表時,就明顯的比其它鎖更糟糕。

4)使用更高層的鎖的話,就能更方便的支持各種不同的類型應用程序,因為這種鎖的開銷比行級鎖小多了。

5)可以用應用程序級鎖來代替行級鎖,例如MySQL中的 GET_LOCK() 和 RELEASE_LOCK()。但它們是勸告鎖(原文:These are advisory locks),因此只能用於安全可信的應用程序中。

6)對於 InnoDB 和 BDB 表,MySQL只有在指定用 LOCK TABLES 鎖表時才使用表級鎖。在這兩種表中,建議最好不要使用 LOCK TABLES,因為 InnoDB 自動采用行級鎖,BDB 用頁級鎖來保證事務的隔離。

 

表鎖的優點及選擇:

1)很多操作都是讀表。

2)在嚴格條件的索引上讀取和更新,當更新或者刪除可以用單獨的索引來讀取得到時:UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;DELETE FROM tbl_name WHERE unique_key_col=key_value;

3)SELECT 和 INSERT 語句並發的執行,但是只有很少的 UPDATE 和 DELETE 語句。

4)很多的掃描表和對全表的 GROUP BY 操作,但是沒有任何寫表。

 

表鎖的缺點:

1)一個客戶端提交了一個需要長時間運行的 SELECT 操作。

2)其他客戶端對同一個表提交了 UPDATE 操作,這個客戶端就要等到 SELECT 完成了才能開始執行。

3)其他客戶端也對同一個表提交了 SELECT 請求。由於 UPDATE的優先級高於 SELECT,所以 SELECT 就會先等到 UPDATE 完成了之後才開始執行,它也在等待第一個 SELECT操作。

 
1.3.       如何避免鎖的資源競爭

1)讓 SELECT 速度盡量快,這可能需要創建一些摘要表。

2)啟動 mysqld 時使用參數 --low-priority-updates。這就會讓更新操作的優先級低於 SELECT。

這種情況下,在上面的假設中,第二個 SELECT 就會在 INSERT 之前執行了,而且也無需等待第一個SELECT 了。

3)可以執行 SET LOW_PRIORITY_UPDATES=1 命令,指定所有的更新操作都放到一個指定的鏈接中去完成。

4)用 LOW_PRIORITY 屬性來降低 INSERT,UPDATE,DELETE 的優先級。

5)用HIGH_PRIORITY 來提高 SELECT 語句的優先級。

6)從MySQL 3.23.7 開始,可以在啟動 mysqld 時指定系統變量 max_write_lock_count 為一個比較低的值,它能強制臨時地提高表的插入數達到一個特定值後的所有 SELECT 操作的優先級。它允許在 WRITE 鎖達到一定數量後有 READ 鎖。

7)當 INSERT 和 SELECT 一起使用出現問題時,可以轉而采用 MyISAM 表,它支持並發的SELECT 和 INSERT 操作。

8)當在同一個表上同時有插入和刪除操作時,INSERT DELAYED 可能會很有用。

9)當SELECT 和 DELETE 一起使用出現問題時,DELETE 的 LIMIT 參數可能會很有用。

10)執行SELECT 時使用 SQL_BUFFER_RESULT 有助於減短鎖表的持續時間。

11)可以修改源代碼 `mysys/thr_lock.c',只用一個所隊列。這種情況下,寫鎖和讀鎖的優先級就一樣了,這對一些應用可能有幫助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved