當前位置: 首頁> 最新文章列表> 如何在mysqli::begin_transaction 中設置和調整事務的隔離級別?

如何在mysqli::begin_transaction 中設置和調整事務的隔離級別?

gitbox 2025-06-17

在PHP 中,使用MySQL 數據庫時, mysqli擴展是最常用的與數據庫進行交互的工具之一。當我們需要進行數據庫操作的事務時, mysqli::begin_transaction方法提供了一種控制事務的開始機制。然而,除了簡單地開啟事務之外,事務的隔離級別也是一個非常重要的考量因素,因為它直接影響到數據的讀取和鎖定行為。

本文將探討如何在mysqli::begin_transaction中設置和調整事務的隔離級別,並講解不同隔離級別的作用和適用場景。

什麼是事務的隔離級別?

事務隔離級別定義了事務中的操作對於其他事務的可見性。不同的隔離級別決定了事務執行時,數據如何與其他並發事務進行交互。主要有以下四種事務隔離級別:

  1. READ UNCOMMITTED(讀未提交) :最低的隔離級別,允許事務讀取其他未提交事務的數據。可能會導致臟讀(Dirty Read)、不可重複讀(Non-repeatable Read)和幻讀(Phantom Read)。

  2. READ COMMITTED(讀已提交) :事務只能讀取已經提交的數據。雖然避免了臟讀,但仍然可能會遇到不可重複讀和幻讀。

  3. REPEATABLE READ(可重複讀) :事務在執行過程中,所有讀取的行數據會被鎖定,其他事務無法修改這些行。避免了臟讀和不可重複讀,但仍可能發生幻讀。

  4. SERIALIZABLE(可串行化) :最高的隔離級別,所有事務會被完全隔離,不會發生臟讀、不可重複讀和幻讀。性能較低,但確保數據的一致性和完整性。

如何在mysqli::begin_transaction中設置事務的隔離級別?

mysqli中,我們可以通過mysqli::set_charset方法來設置事務的隔離級別。通常,這需要在調用begin_transaction之前,使用SET TRANSACTION ISOLATION LEVEL SQL 語句來設定。

以下是設置和調整事務隔離級別的步驟:

1. 創建數據庫連接

首先,創建一個與MySQL 數據庫的連接:

 <span><span><span class="hljs-variable">$mysqli</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">mysqli</span></span><span>(</span><span><span class="hljs-string">"localhost"</span></span><span>, </span><span><span class="hljs-string">"user"</span></span><span>, </span><span><span class="hljs-string">"password"</span></span><span>, </span><span><span class="hljs-string">"database"</span></span><span>);

</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;connect_error) {
    </span><span><span class="hljs-keyword">die</span></span><span>(</span><span><span class="hljs-string">"連接失敗: "</span></span><span> . </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;connect_error);
}
</span></span>

2. 設置事務的隔離級別

在調用begin_transaction之前,可以使用SQL 語句來指定事務的隔離級別。例如,若要設置為REPEATABLE READ隔離級別:

 <span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"</span></span><span>);
</span></span>

你可以根據需要選擇合適的隔離級別。

3. 開始事務

在設置了事務的隔離級別後,使用begin_transaction開始事務:

 <span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">begin_transaction</span></span><span>();
</span></span>

4. 執行事務操作

在事務中執行一系列的數據庫操作:

 <span><span><span class="hljs-keyword">try</span></span><span> {
    </span><span><span class="hljs-comment">// 執行數據庫操作</span></span><span>
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"INSERT INTO table_name (column1, column2) VALUES ('value1', 'value2')"</span></span><span>);

    </span><span><span class="hljs-comment">// 提交事務</span></span><span>
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">commit</span></span><span>();
} </span><span><span class="hljs-keyword">catch</span></span><span> (</span><span><span class="hljs-built_in">Exception</span></span><span> </span><span><span class="hljs-variable">$e</span></span><span>) {
    </span><span><span class="hljs-comment">// 如果出錯,回滾事務</span></span><span>
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">rollback</span></span><span>();
}
</span></span>

5. 結束事務

根據事務執行情況,可以選擇提交或回滾事務:

  • 使用$mysqli->commit()提交事務。

  • 使用$mysqli->rollback()回滾事務。

示例:完整代碼

<span><span><span class="hljs-meta">&lt;?php</span></span><span>
</span><span><span class="hljs-comment">// 創建數據庫連接</span></span><span>
</span><span><span class="hljs-variable">$mysqli</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">mysqli</span></span><span>(</span><span><span class="hljs-string">"localhost"</span></span><span>, </span><span><span class="hljs-string">"user"</span></span><span>, </span><span><span class="hljs-string">"password"</span></span><span>, </span><span><span class="hljs-string">"database"</span></span><span>);

</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;connect_error) {
    </span><span><span class="hljs-keyword">die</span></span><span>(</span><span><span class="hljs-string">"連接失敗: "</span></span><span> . </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;connect_error);
}

</span><span><span class="hljs-comment">// 設置事務隔離級別</span></span><span>
</span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"</span></span><span>);

</span><span><span class="hljs-comment">// 開始事務</span></span><span>
</span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">begin_transaction</span></span><span>();

</span><span><span class="hljs-keyword">try</span></span><span> {
    </span><span><span class="hljs-comment">// 執行一些數據庫操作</span></span><span>
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"INSERT INTO products (name, price) VALUES ('product1', 100)"</span></span><span>);
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">query</span></span><span>(</span><span><span class="hljs-string">"UPDATE products SET price = 150 WHERE name = 'product2'"</span></span><span>);

    </span><span><span class="hljs-comment">// 提交事務</span></span><span>
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">commit</span></span><span>();
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"事務提交成功!"</span></span><span>;
} </span><span><span class="hljs-keyword">catch</span></span><span> (</span><span><span class="hljs-built_in">Exception</span></span><span> </span><span><span class="hljs-variable">$e</span></span><span>) {
    </span><span><span class="hljs-comment">// 回滾事務</span></span><span>
    </span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">rollback</span></span><span>();
    </span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"事務回滾: "</span></span><span> . </span><span><span class="hljs-variable">$e</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">getMessage</span></span><span>();
}

</span><span><span class="hljs-comment">// 關閉數據庫連接</span></span><span>
</span><span><span class="hljs-variable">$mysqli</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">close</span></span><span>();
</span><span><span class="hljs-meta">?&gt;</span></span><span>
</span></span>

隔離級別的選擇

選擇合適的隔離級別通常取決於業務需求和系統的並發情況。以下是一些常見場景的建議:

  • 高並發的查詢操作:選擇READ COMMITTEDREPEATABLE READ ,以平衡性能和數據一致性。

  • 需要嚴格保證數據一致性:選擇SERIALIZABLE ,它會確保事務完全隔離,但性能會受到較大影響。

  • 性能要求較高的應用:在性能要求較高的情況下,可以選擇READ UNCOMMITTED ,但要小心臟讀問題。

總結

在PHP 中使用mysqli擴展時,設置事務的隔離級別是一個非常重要的操作。通過使用SET TRANSACTION ISOLATION LEVEL語句,我們能夠在mysqli::begin_transaction之前調整隔離級別,以確保事務執行的可靠性和一致性。選擇合適的隔離級別對於數據庫性能和數據一致性有著重要影響,因此在開發過程中應根據業務需求謹慎選擇合適的事務隔離級別。