1. 程式人生 > >【Laravel】資料庫事務

【Laravel】資料庫事務

最近公司專案集成了一個支付的模組。由於網路世界是不確定的。說不定哪個操作就出了問題。為了保證資料的正確性我們不得不考慮使用資料庫事務這一特性。本文做一個Laravel資料庫事務的介紹。

知識回顧

 事務將一堆的資料庫操作組合到一個工作單元中執行

 、事務的四個特性

1、原子性(atomicity)原子性是指整個資料庫事務是不可分割的工作單位。
2、一致性(consistency)一致性指事務將資料庫從一種狀態轉變為下一種一致的狀態。在事務開始之前和事務結束之後,資料庫的完整性約束沒有被破壞。

3、隔離性(isolation)一個事務的影響在該事務提交之前對其他事務都不可見------這通過鎖來實現。



4、永續性(durability)事務一旦提交,其結果就是永久性的。

Mysql中的儲存引擎

1Mysql伺服器層不管理事務,事務是由下層的儲存引擎實現的。

2在MySQL 5.1之前的版本中,預設的搜尋引擎是MyISAM,從MySQL 5.5之後的版本中,預設的搜尋引擎變更為InnoDB。

3Mysql提供了兩種事務型的儲存引擎:InnoDB和NDB Cluster,而MyISAM不支援事務。

死鎖

1.什麼是死鎖?死鎖是指兩個或者多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而導致惡性迴圈。

2.為什麼要避免死鎖?導致慢查詢

3.如何解決?Mysql提供了死鎖檢測和死鎖超時機制,

Laravel中的事務

方式一:閉包方式實現事務

您可以在 DB facade 上使用 transaction 方法,在資料庫事務中執行一組操作。如果在事務 Closure 中丟擲一個異常,那麼事務將自動回滾。如果 Closure 成功執行,事務將自動被提交。您不需要擔心在使用事務方法時手動回滾或提交。
//模擬使用者233向用戶666轉賬1元
DB::transaction(function () {
    DB::table('transactions')->where('user_id',666)increment('blance' , 1);

    DB::table('transactions')->where('user_id',233)->decrement('balance' , 1
); });
transaction 方法接受一個可選的第二個引數,該引數定義在發生死鎖時,應該重新嘗試事務的次數。一旦這些嘗試都用盡了,就會丟擲一個異常:

DB::transaction(function () {
DB::table('transactions')->where('user_id',666)increment('blance' , 1);

   DB::table('transactions')->where('user_id',233)->decrement('balance' , 1);
}, 3);

如果閉包內部需要呼叫外部的引數可以使用下面的方式向閉包傳參:

DB::transaction(function use ($amount) () {
DB::table('transactions')->where('user_id',666)increment('blance' , $amount);

   DB::table('transactions')->where('user_id',233)->decrement('balance' , $amount);
}, 3);

方式二:手動操作事務

如果您想要手工開始一個事務,並且對回滾和提交有完全的控制,那麼您可以在 DB facade 上使用:

beginTransaction 方法:

DB::beginTransaction(); 您可以通過 rollBack 方法回滾事務:
DB::rollBack();
最後, 您可以通過 commit 方法提交事務,當事務進行提交(commit)或者回滾(rollBack)時都會取消鎖:
DB::commit();
例子如下:

DB::beginTransaction();//開啟事務
try {
    //這裡省略了業務邏輯程式碼    if($isSuccess){        DB::commit();//成功,提交事務    }   //思考->如果事務開啟不提交會發生什麼後果???
} catch(\Illuminate\Database\QueryException $ex) {
    DB::rollback();//失敗,回滾事務
    echo 'error';
}
echo 'success';

注意:使用 DB 門面的事務方法還可以用於控制查詢構建器和 Eloquent ORM 的事務。

如果MySQL存在沒有提交的事務,那麼這時候 AUTOCOMMIT 自動提交的引數應該是為 0 的。如果通過其他的語言的MySQL驅動來操作的話,這些驅動一般都帶有自動恢復 AUTOCOMMIT 的功能,在請求處理完成後會自動 ROLLBACK 沒有處理的事務。