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的事務已經總結介紹完了,如有問題請及時討論糾正,謝謝。