程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> 細化解析:帶你輕松接觸事務和原子操作

細化解析:帶你輕松接觸事務和原子操作

編輯:關於MYSQL數據庫

MySQL服務器(3.23至該系列的最高版本,所有4.0版本,以及更高版本)支持采用InnoDB和BDB事務存儲引擎的事務。InnoDB提供了全面的ACID兼容性。

MySQL服務器中的其他非事務性存儲引擎(如MyISAM)遵從不同的數據完整性范例,稱之為“原子操作”。按照事務術語,MyISAM表總能高效地工作在AUTOCOMMIT=1模式下。原子操作通常能提供可比較的完整性以及更好的性能。

 

由於MySQL服務器支持兩種范例,因而你能決定是否利用原子操作的速度更好地服務於你的應用程序,或使用事務特性。該選擇可按表進行。

 

正如所闡述的那樣,事務性和非事務性表類型之間的權衡主要取決於性能。事務性表對內存和磁盤空間的要求更高,CPU開銷也更大。另一方面,多種事務性表類型,如InnoDB,也能提供很多顯著特性。MySQL服務器的模塊化設計允許同時使用不同的存儲引擎,以滿足不同的要求,並在所有情形下,提供最佳性能。

 

但是,即便使用非事務性MyISAM表,你將如何使用MySQL服務器的特性來保持嚴格的完整性呢?這些特性與事務性表類型相比又如何呢?

 

1. 如果應用程序采用了特定的編寫方式,依賴於在關鍵情況下能夠調用ROLLBACK而不是COMMIT,那麼事務性類型更方便。使用事務,還能確保未完成的更新或崩潰的活動不被提交到數據庫,能為服務器提供自動回滾的機會,並保存你的數據庫。

 

如果使用非事務性表,MySQL服務器幾乎在所有情況下均允許你解決潛在的問題,方式是在更新前進行簡單檢查,並運行檢查數據庫一致性的簡單腳本,如果出現不一致性,該腳本能自動修復它或給出告警。注意,僅使用MySQL日志或增加額外日志,通常能完美地更正表,同時不會造成數據完整性損失。

 

2. 在很多情況下,能夠對關鍵的事務更新進行重寫,使之成為“原子”類型。一般而言,所有由事務解決的完整性問題均能用LOCK TABLES或原子更新解決,從而確保了服務器不會自動中斷,後者是事務性數據庫系統的常見問題。

 

3. 為了安全使用MySQL服務器,無論是否使用事務性表,僅需啟用備份和二進制日志功能。這樣,你就能解決使用其他事務性數據庫系統時遇到的任何問題。無論使用的數據庫系統是什麼,啟用備份總是個好主意。

 

事務范型有自己的優點和不足之處。很多用戶和應用程序開發人員喜歡這類簡單性,在出現問題時或必要時,通過代碼解決問題。但是,即使你是原子操作范型的新手,或更熟悉事務,也請考慮非事務性表的速度益處,與經過優化調整的最快的事務性表相比,它的速度快3~5倍。

 

在完整性具有最高重要性的情況下,即使是對非事務性表,MySQL也能提供事務級別的可靠性和安全性。如果使用LOCK TABLES鎖定了表,所有更新均將被暫時中止直至完整性檢查完成。如果你獲得了對某一表的READ LOCAL鎖定(與寫鎖定相對),該表允許在表尾執行並行插入,當其他客戶端執行插入操作時,允許執行讀操作。新插入的記錄不會被有讀鎖定屬性的客戶端看到,直至解除了該鎖定為止。使用INSERT DELAYED,能夠將插入項置於本地隊列中,直至鎖定解除,不會讓客戶端等待插入完成。

從我們賦與其名稱的意義上,“原子”絕非不可思議的。它僅意味著,你能確信在每個特性更新運行的同時,其他用戶不能干涉它,而且不會出現自動回滾(如果你不小心,對於事務性表,這種情況可能發生)。MySQL服務器還能保證不存在髒讀。

下面列出了使用非事務性表的一些技術:

 

· 對於需要事務的循環,通常能使用LOCK TABLES進行編碼,不需要光標來更新正在處理的記錄。

 

· 要想避免使用ROLLBACK,可采取下述策略:

 

1. 使用LOCK TABLES鎖定所有希望訪問的表。

 

2. 執行更新前,測試必須為真的條件。

 

3. 如果一切正常,執行更新。

 

4. 使用UNLOCK TABLES解除鎖定。

 

與使用具有回滾可能性的事務性表相比,它通常具有更快的速度,雖然並非始終如此。該解決方案唯一不能處理的情形是,在更新中途殺死了線程。在這種情況下,將釋放所有鎖定,但某些更新可能尚未執行。

 

◆也可以使用函數在單一操作中更新記錄。采用下述技術,能獲得效率很高的應用程序。

◆根據其當前值更改列。

◆僅更新出現實際變化的列。

 

例如,當我們更新某些客戶信息時,僅更新已更改的客戶數據,與原始行相比,僅測試已更改的數據或依賴於已更改數據的數據是否未出現變化。對於已更改數據的測試,它是通過UPDATE語句的WHERE子句完成的。如果記錄未更新,將向客戶端發出消息: “一些你改變的數據已被其他用戶更改”。接下來,我們在窗口中給出了舊行和新行,以便用戶決定使用哪個版本。

 

這給出了與列鎖定類似的結果,但效果更好,使用相對於其當前值的值,僅更新了某些列。這意味著,典型的UPDATE語句與下面給出的類似:

 

UPDATE tablename SET pay_back=pay_back+125; 
UPDATE customer
  SET    
customer_date='current_date',    
address='new address',    
phone='new phone',    
money_owed_to_us=money_owed_to_us-125  
WHERE    
customer_id=id AND address='old address' AND phone='old phone';

 

它很有效,即使其他客戶端更改了pay_back或money_owed_to_us列中的值,也能使用。

 

·在很多情況下,用戶希望將LOCK TABLES和/或ROLLBACK用於管理唯一ID。可以在不使用鎖定功能或回滾的情況下,使用AUTO_INCREMENT列以及LAST_INSERT_ID() SQL函數或MySQL_insert_id() C API函數。

我們通常能使用代碼來處理行級鎖定方面的需求。在某些情況下,實際上不需要它,InnoDB表支持行級鎖定。通過MyISAM表,能夠在表中使用標志列,並完成類似下面的操作:

 

UPDATE tbl_name SET row_flag=1 WHERE id=ID;

如果找到行,而且原始行中的row_flag不是1,對於受影響的行數,MySQL返回1。

你可以認為MySQL將前述查詢更改為:

 

UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved