簡單介紹 Laravel 的 DB Transactions

程式技術
sharkHead

MySQL 資料庫,PHP 的好夥伴,在當前的版本中,MySQL 資料庫基本上都是使用 innoDB 作為預設的資料庫引擎。

innoDB 與之前 MyISAM 相比,支援了 ACID 相容的交易 (Transaction) 功能。

所謂的交易,是資料庫管理系統執行過程中的一個邏輯單位,由一個有限的資料庫操作序列構成。

資料庫交易具備 ACID 性質,指的是:

  • 原子性 (Atomicity):交易作為一個整體被執行,包含在其中的對資料庫的操作要麼全部被執行,要麼都不執行。
  • 一致性 (Consistency):交易應確保資料庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是資料庫中的資料應滿足完整性約束。
  • 隔離性 (Isolation):多個交易並行執行時,一個交易的執行不應影響其他交易的執行。
  • 永續性 (Durability):已被提交的交易對資料庫的修改應該永久儲存在資料庫中。

簡單來說,資料庫需要處理從網站那裏傳來的上千、上萬甚至上百萬的交易,如果每筆交易會互相影響,或是說交易到一半停止,都會導致資料庫中的資料出現錯誤。

在 Laravel 中,也有提供一個交易的功能。

DB::transaction();

使用範例如下。

use Illuminate\Support\Facades\DB;


// 如果下方的任一資料庫操作失敗,資料就會回滾(rollback)至操作前的狀態
DB::transaction(function () {
    DB::update('update users set votes = 1');

    DB::delete('delete from posts');
});

什麼時候會使用這樣功能呢?

舉例來說,以部落格文章為例,當我們寫好文章內容並設定好標籤,將新增文章請求發送至後端,此時後端會做兩件事情。

  1. 新增一篇文章。
  2. 更新文章與標籤的關聯表。

這個時候我們就可以使用 transaction 功能確保這兩件事情都會執行或是都不執行,如果有任何一項操作執行失敗,資料庫就會回滾至執行前的資料狀態。

// 新增文章
public function store(PostRequest $request, Post $post)
{
    $post->fill($request->validated());
    $post->user_id = auth()->id();

    // 將傳過來的 JSON 資料轉成 array
    $tagIdsArray = $this->tagsJsonToTagIdsArray($request->tags);

    DB::transaction(function () use ($post, $tagIdsArray) {
        // 新增文章
        $post->save();

        // 在關聯表新增關聯
        $post->tags()->attach($tagIdsArray);
    });

    return redirect()->to($post->link_with_slug)->with('success', '成功新增文章!');
}

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

0 則留言