1. 程式人生 > >Mysql事務使用總結

Mysql事務使用總結

事務使用總結:

MySQL事務主要用來處理資料量大、資料複雜度高的資料操作,最經典的使用場景是銀行的轉賬:需要先從銀行賬戶A中取出錢,然後再存入銀行賬戶B中,如果中間出現問題,而沒有事務的保證,那麼就會出現B收不到錢,而A支出錢又回不到自己的賬戶的嚴重問題,那麼有了事務機制,這個問題就解決了。

事務的特點

事務的ACID

事務的鎖定

事務的隔離

事務的使用

一、事務的特點

1、在mysql中,只有資料庫引擎InnoDB支援事務機制;

2、事務可用來維護資料結構及資料的完整性,確保批量的操作要麼全部執行,要麼全部不執行;

3、事務是用來管理資料表的insert、update及delete的

二、事務的ACID

1、A(Atomicity),即事務的原子性

一組事務操作,要麼都成功,要麼都撤回。

2、C(Consistency),即事務的穩定性

有非法資料操作,如:外來鍵約束,事物撤回。

3、I(Isolation),即事務的隔離性

事務是獨立執行的,一個事務的操作如果影響了另一個事物,那麼另一個事務就會撤回執行,要做到事務100%的隔離,需要犧牲速度和效能。

4、D(Durability),即事務的可靠性

當資料庫崩潰之後,InnoDB資料庫表驅動會利用日誌檔案進行資料的重構修改,需要注意的是:安全性和效能速度不可兼得。

三、事務的隔離

1、併發時遇到的問題

在事務併發操作時,經常出現一些問題,這些問題可用幾個術語名詞描述:

A、髒讀

一個事務讀取了另一個事務併發寫的未提交的資料,比如:事務A讀取了事務B寫入的資料,但是B事務並未提交,後來其撤銷了修改,此時事務A就讀取了不該讀取的資料。

B、幻讀

一個事務重複讀取資料,在獲得的資料行中發現某些資料是其它事務最近操作的資料,比如:事務A反覆執行查詢語句查詢資料表,而這時另一事務B正在操作該表,恰好的是事務B操作的資料正符合事務A查詢的條件,而事務A再讀取時,發現結果集發生了變化,這在併發事務時經常出現。

C、不可重複讀

一個事務重複讀取之前讀取過的資料,後發現讀取的資料被另一個事務所修改,比如:事務A反覆讀取指定的資料,而此時事務B正好操作該資料,當事務A再次查詢時,發現之前讀取的資料已經變化。

注:

上面事務併發出現的問題,可以通過設定事務的隔離來處理,但不能完全依賴事務隔離,而是應該在應用程式中恰當的使用鎖來控制併發訪問,兩者的結合是解決的問題關鍵。

2、事務的隔離級別

事務隔離級別分為4種:

READ UNCOMMITED // 允許幻讀,髒讀及不可重複讀;

READ COMMITED   // 允許幻讀和不可重複讀,不允許髒讀;

REPEATABLE READ // 允許幻讀,不允許髒讀和不可重複讀;

SERIALIZABLE READ // 不允許幻讀,髒讀及不可重複讀;

注:

Mysql預設的是REPEATABLEREAD級別。另外,隨著事務的隔離級別越高,併發執行的效能就越低,所以適當選擇級別並結合業務需求來選定級別設定。

3、設定事務隔離級別

A、查詢Mysql系統隔離預設級別:

Mysql> SELECT @@global.tx_isolation;

結果:

@@global.tx_isolation

REPEATABLE-READ

B、查詢Mysql會話隔離預設級別:

Mysql> SELECT @@tx_isolation;

結果:

@@tx_isolation

REPEATABLE-READ

C、修改系統及會話隔離級別

這裡我們將事務的級別修改為READ COMMITED:

mysql> SET global transaction isolation level readcommitted;

mysql> SET session transaction isolation level readcommitted;

結果:

四、事務的鎖定

為什麼要給事務加鎖?是因為高併發訪問操作資料時,會存在正在讀取某資料時,其它程序會刪除會修改該資料,為了保證資料的完整性,需要對程序共享資料加鎖控制。

事務鎖的分類:

按照對資料的操作型別劃分:

讀鎖(共享鎖)-

針對同一塊資料,多個讀操作可同時進行互補影響。

寫鎖(排它鎖)-

針對同一塊資料,當前寫操作未完成,它會阻止其它操作進行。

按照鎖定資料的範圍劃分:

表鎖 -

MyIsam引擎預設使用的鎖。當寫入資料時,把整張表鎖住,其它的讀,寫操作都不進行,一律等待當前寫操作完成,特點:開銷小,併發量小。

行鎖 -

InnoDB及Falcon引用預設使用的鎖。當寫入資料時,把當前操作的資料行鎖定,其它讀,寫操作一律等待,特點:開銷適中,併發量大。

注:

Mysql是一種開放式資料庫架構,是允許自定義儲存引擎的,而Oracle及Sql server是不允許自定義修改的。

五、事務的使用

1、事務的操作

開啟一個事務:

START TRANSACTION | BEGIN;

提交關閉事務;

COMMIT;

儲存事務快照:

SAVE POINT save_point_name;  // save_point_name儲存事務點名字

回滾事務(點):

ROLLBACK save_point_name;

2、PHP使用事務

這裡以關聯資料表t_product_item和 t_product_detail為例說明事務的使用。這兩張表是通過外來鍵關聯的,這裡為了模擬驗證事務的原子特性,故向兩張資料表中插入資料,首先向t_product_item插入資料成功,而t_product_detail插入失敗,那麼因為使用了事務機制,所以t_product_item插入成功的資料會恢復插入前資料條數)。

A、php程式碼

<?php

// 連結mysql

       $conn =mysql_connect('localhost','root','');

       if(!$conn) {

           echo 'Could notconnect the db server!';

           return;

       }

       // 選擇資料庫

       mysql_select_db('db_study_mysql');

       /* 事務處理 */

       // 設定事務不自動提交 因為預設mysql自動提交

       mysql_query('SET AUTOCOMMIT =0');

       // 開始事務定義

       mysql_query('BEGIN');

       // 如果插入資料失敗 則回滾

       $piSQL = 'INSERT INTOt_product_item(pino,piname,piimage,piprice,pifid) VALUES(';

       $piSQL .='"PINO20160320003"'.','.'"頂級肥牛"'.','.'"http://images.cwteam.com/uploads/imgs/2016320001/23123212.jpg"'.',';

       $piSQL .= '60.00'.','.'2'.');';

       $piID = mysql_query($piSQL,$conn);

       if($piID) {

           echo '向t_product_item插入資料成功!</br>';

           $pdSQL = 'INSERT INTOt_product_detail(pdno,pdname,pdprice,pddesc,pdrule,pdfid) VALUES(';

           $pdSQL .= '頂級肥牛'.','.'http://images.cwteam.com/uploads/imgs/2016320001/23123212.jpg'.',';

           $pdSQL .= '60.00'.','.'法式小餐廳,由頂級餐廳大廚掌勺定製,趕緊來吧,限時搶購中,截止23號'.',';

           $pdSQL .= '材質不詳,但好吃哦!'.','.'4'.');'; // 因為pdfid外來鍵值 不存在4 所以插入會失敗

           $pdID =mysql_query($pdSQL,$conn);

           if($pdID) {

              echo '向t_product_detail插入資料成功!</br>';

           } else {

              echo '向t_product_detail插入資料失敗,已經回滾事務!</br>';

              mysql_query('ROLLBACK');

           }

       } else {

           echo '向t_product_item插入資料失敗,已經回滾事務!</br>';

           mysql_query('ROLLBACK');

       }

       // 提交關閉事務

       mysql_query('COMMIT');

       // 關閉資料庫連結

       mysql_close($conn);

?>

B、瀏覽器結果:


C、資料庫結果:

因為使用事務,所以這裡的t_product_item資料不變,對比使用事務的前後,這裡不做介紹,因為本人已經測試過沒問題。

Ps:感興趣的同學最好驗證下。


好了,到這裡關於Mysql的事務已經總結介紹完了,如有問題請及時討論糾正,謝謝。