1.資料庫事務
事務(Transaction)是並發控制的基本單位。所謂的事務,它是一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位。例如,銀行轉賬工作:從一個帳號扣款並使另一個帳號增款,這兩個操作要麼都執行,要麼都不執行。所以,應該把它們看成一個事務。事務是資料庫維護資料一致性的單位,在每個事務結束時,都能保持資料一致性。事務具有以下4個基本特徵:● Atomic(原子性):事務中包含的操作被看做一個邏輯單元,這個邏輯單元中的操作要麼全部成功,要麼全部失敗。● Consistency(一致性):只有合法的資料可以被寫入資料庫,否則事務應該將其復原到最初狀態。● Isolation(隔離性):事務允許多個使用者對同一個資料進行並發訪問,而不破壞資料的正確性和完整性。同時,並行事務的修改必須與其他並行事務的修改相互獨立。● Durability(持久性):事務結束後,交易處理的結果必須能夠得到固化。
2.實現資料庫交易管理的方式
2.1 編碼式事務
在代碼中顯式調用beginTransaction()、commit()、rollback()等交易管理相關方法就是編碼式交易管理。編碼式交易管理需要程式員在具體的業務代碼中顯式調用交易管理的相關方法,並顯式地根據各種條件來判斷是提交還是復原。這種方式在業務簡單的系統中還可應付,對於業務複雜的系統可能會因為少了某些條件判斷導致錯誤的提交或復原,尤其對於業務需求變動極其頻繁的系統可能會因為判斷條件沒有及時根據業務的調整而修改而導致錯誤的提交和復原。由於編碼式事務存在需要將交易管理與商務邏輯代碼耦合,並且難以判斷或及時更新復原條件,甚至出現意料之外的事務嵌套等原因,因此不推薦使用編碼式方式管理事務。
2.2 聲明式事務
TP系統的聲明式交易管理機制在底層是建立在TP架構的行為擴充機制之上的。其實質是在控制器的目標方法執行前開啟事務,在執行完控制器的目標方法之後根據實際情形提交或復原事務。
聲明式事務最大的優點就是不需要在具體的商務邏輯代碼中攙雜交易管理的代碼,只需在模組配置中聲明需要開啟交易管理的方法,即可將事務運用到商務邏輯中。
3.TP項目的聲明式交易處理機制的實現
1)在系統常量配置中增加兩個常量:
// 開啟資料庫事務define('DB_TRANS_ENABLE', true);// 資料庫事務全域標誌define('DB_TRANS_VAR', 'tx_comment'); 2)在BaseModel中重載TP架構的Model類中的add、addAll、delete、execute、save方法
具體可查看相關代碼。
3)在MyActionBeginBehavior的run方法中根據系統全域事務開關和模組配置判斷是否開啟資料庫事務
// 開啟資料庫事務 by 凡牆 2015.09.14 18:05$db_trans_enable = C('DB_TRANS_ENABLE');if(defined('DB_TRANS_ENABLE') && DB_TRANS_ENABLE && is_array($db_trans_enable) && in_array(strtolower(CONTROLLER_NAME . '.' . ACTION_NAME), $db_trans_enable)) { env(DB_TRANS_VAR, true); M()->startTrans();} 4)在MyActionEndBehavior的run方法中根據系統全域事務開關、模組配置以及環境變數DB_TRANS_VAR的值判斷是否提交事務
// 處理資料庫事務 by 凡牆 2015.09.14 18:05$db_trans_enable = C('DB_TRANS_ENABLE');if(defined('DB_TRANS_ENABLE') && DB_TRANS_ENABLE && is_array($db_trans_enable) && in_array(strtolower(CONTROLLER_NAME . '.' . ACTION_NAME), $db_trans_enable)) { $tx_commit = env(DB_TRANS_VAR); if ($tx_commit === false) { // 復原 M()->rollback(); } else { // 提交事務 M()->commit(); }} 5)強制復原
在需要強制復原的代碼處將環境變數 DB_TRANS_VAR 的值設為 false,則系統將在目的方法結束後復原。
4.存在的問題
4.1 資料庫讀寫分離
資料庫讀寫分離後,按TP架構的機制,一次請求將至少建立兩個資料庫連接,因此目前的聲明式事務實現機制需要針對讀串連和寫串連分別根據需要管理事務。
4.2 事務控制的細度
和編碼式事務相比,聲明式事務的最細粒度只能浸入到控制器的方法層級,沒法做到像編碼式事務那樣可以浸入到代碼塊層級,甚至無法做到對非控制器的方法的交易管理。待擴充。
4.3 事務對資料的影響
幻讀phantom read:事務1讀取記錄時事務2增加了記錄並提交,事務1再次讀取時可以看到事務2新增的記錄;不可重複讀取unrepeatable read:事務1讀取記錄時,事務2更新了記錄並提交,事務1再次讀取時可以看到事務修改後的記錄;髒讀dirty read:事務1更新了記錄,但沒有提交,事務2讀取了更新後的行,然後事務T1復原,現在T2讀取無效。幻讀、不可重複讀取、髒讀等問題可通過資料庫的交易隔離等級解決,待最佳化。
需要注意的是,若在資料模型層對資料做了緩衝處理,系統開啟事務後可能導致“髒資料”的問題,因此對於一些重要資料欄位的讀寫不能依賴於緩衝中的資料。
4.4 分散式交易
資料庫分庫分表或系統採用微服務架構後將出現分散式交易問題。待研究。