Mysql 事務的講解

來源轉載自:http://www.cnblogs.com/ymy124/p/3718439.html

MySQL的事務支持不是綁定在MySQL服務器本身,而是與存儲引擎相關1.MyISAM:不支持事務,用于只讀程序提高性能 2.InnoDB:支持ACID事務、行級鎖、并發 3.Berkeley DB:支持事務

一個事務是一個連續的一組數據庫操作,就好像它是一個單一的工作單元進行。換言之,永遠不會是完整的事務,除非該組內的每個單獨的操作是成功的。如果在事務的任何操作失敗,則整個事務將失敗。
實際上,會俱樂部許多SQL查詢到一個組中,將執行所有的人都一起作為事務的一部分。
事務的特性: 事務有以下四個標準屬性的縮寫ACID,通常被稱為:
原子性: 確保工作單元內的所有操作都成功完成,否則事務將被中止在故障點,和以前的操作將回滾到以前的狀態。
一致性: 確保數據庫正確地改變狀態后,成功提交的事務。
隔離性: 使事務操作彼此獨立的和透明的。
持久性: 確保提交的事務的結果或效果的系統出現故障的情況下仍然存在。
在MySQL中,事務開始使用COMMIT或ROLLBACK語句開始工作和結束。開始和結束語句的SQL命令之間形成了大量的事務。
COMMIT & ROLLBACK: 這兩個關鍵字提交和回滾主要用于MySQL的事務。
當一個成功的事務完成后,發出COMMIT命令應使所有參與表的更改才會生效。
如果發生故障時,應發出一個ROLLBACK命令返回的事務中引用的每一個表到以前的狀態。
可以控制的事務行為稱為AUTOCOMMIT設置會話變量。如果AUTOCOMMIT設置為1(默認值),然后每一個SQL語句(在事務與否)被認為是一個完整的事務,并承諾在默認情況下,當它完成。 AUTOCOMMIT設置為0時,發出SET AUTOCOMMIT =0命令,在隨后的一系列語句的作用就像一個事務,直到一個明確的COMMIT語句時,沒有活動的提交。
可以通過使用mysql_query()函數在PHP中執行這些SQL命令。
通用事務例子 這一系列事件是獨立于所使用的編程語言,可以建立在任何使用的語言來創建應用程序的邏輯路徑。可以通過使用mysql_query()函數在PHP中執行這些SQL命令。
BEGIN WORK開始事務發出SQL命令
發出一個或多個SQL命令,如SELECT,INSERT,UPDATE或DELETE
檢查是否有任何錯誤,一切都依據的需要。
如果有任何錯誤,那么問題ROLLBACK命令,否則發出COMMIT命令。
在MySQL中的事務安全表類型:
如果打算使用MySQL事務編程,那么就需要一種特殊的方式創建表。有很多支持事務但最流行的是InnoDB表類型。
從源代碼編譯MySQL時,InnoDB表支持需要特定的編譯參數。如果MySQL版本沒有InnoDB支持,請互聯網服務提供商建立一個版本的MySQL支持InnoDB表類型,或者下載并安裝Windows或Linux/UNIX的MySQL-Max二進制分發和使用的表類型在開發環境中。如果MySQL安裝支持InnoDB表,只需添加一個的TYPE=InnoDB 定義表創建語句。例如,下面的代碼創建InnoDB表tcount_tbl:

代碼如下
復制代碼

root@host# mysql -u root -p password;Enter password:*******mysql> use TUTORIALS;Database changedmysql> create table tcount_tbl -> ( -> tutorial_author varchar(40) NOT NULL, -> tutorial_count INT -> ) TYPE=InnoDB;Query OK, 0 rows affected (0.05 sec)

可以使用其他GEMINI或BDB表類型,但它取決于您的安裝,如果它支持這兩種類型。
由于項目設計里面,牽扯到了金錢的轉移,于是就要用到MYSQL的事務處理,來保證一組處理結果的正確性。用了事務,就不可避免的要犧牲一部分速度,來保證數據的正確性。只有InnoDB支持事務
事務 ACID Atomicity(原子性)、Consistency(穩定性)、Isolation(隔離性)、Durability(可靠性)
1、事務的原子性一組事務,要么成功;要么撤回。
2、穩定性有非法數據(外鍵約束之類),事務撤回。
3、隔離性事務獨立運行。一個事務處理后的結果,影響了其他事務,那么其他事務會撤回。事務的100%隔離,需要犧牲速度。
4、可靠性軟、硬件崩潰后,InnoDB數據表驅動會利用日志文件重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項 決定什么時候吧事務保存到日志里。開啟事務START TRANSACTION 或 BEGIN
提交事務(關閉事務)COMMIT
放棄事務(關閉事務)ROLLBACK
折返點SAVEPOINT adqoo_1ROLLBACK TO SAVEPOINT adqoo_1發生在折返點 adqoo_1 之前的事務被提交,之后的被忽略
事務的終止
設置“自動提交”模式SET AUTOCOMMIT = 0每條SQL都是同一個事務的不同命令,之間由 COMMIT 或 ROLLBACK隔開掉線后,沒有 COMMIT 的事務都被放棄
事務鎖定模式
系統默認: 不需要等待某事務結束,可直接查詢到結果,但不能再進行修改、刪除。缺點:查詢到的結果,可能是已經過期的。優點:不需要等待某事務結束,可直接查詢到結果。
需要用以下模式來設定鎖定模式
1、SELECT …… LOCK IN SHARE MODE(共享鎖)查詢到的數據,就是數據庫在這一時刻的數據(其他已commit事務的結果,已經反應到這里了)SELECT 必須等待,某個事務結束后才能執行
2、SELECT …… FOR UPDATE(排它鎖)例如 SELECT * FROM tablename WHERE id<200那么id<200的數據,被查詢到的數據,都將不能再進行修改、刪除、SELECT …… LOCK IN SHARE MODE操作一直到此事務結束
共享鎖 和 排它鎖 的區別:在于是否阻斷其他客戶發出的 SELECT …… LOCK IN SHARE MODE命令
3、INSERT / UPDATE / DELETE所有關聯數據都會被鎖定,加上排它鎖
4、防插入鎖例如 SELECT * FROM tablename WHERE id>200那么id>200的記錄無法被插入
5、死鎖自動識別死鎖先進來的進程被執行,后來的進程收到出錯消息,并按ROLLBACK方式回滾innodb_lock_wait_timeout = n 來設置最長等待時間,默認是50秒
事務隔離模式
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVELREAD UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE1、不帶SESSION、GLOBAL的SET命令只對下一個事務有效2、SET SESSION為當前會話設置隔離模式3、SET GLOBAL為以后新建的所有MYSQL連接設置隔離模式(當前連接不包括在內)
隔離模式
READ UNCOMMITTED不隔離SELECT其他事務未完成的修改(未COMMIT),其結果也考慮在內
READ COMMITTED把其他事務的 COMMIT 修改考慮在內同一個事務中,同一 SELECT 可能返回不同結果
REPEATABLE READ(默認)不把其他事務的修改考慮在內,無論其他事務是否用COMMIT命令提交過同一個事務中,同一 SELECT 返回同一結果(前提是本事務,不修改)
SERIALIZABLE和REPEATABLE READ類似,給所有的SELECT都加上了 共享鎖
出錯處理根據出錯信息,執行相應的處理
mysql事物處理實例
MYSQL的事務處理主要有兩種方法1.用begin,rollback,commit來實現 begin開始一個事務 rollback事務回滾 commit 事務確認2.直接用set來改變mysql的自動提交模式 mysql默認是自動提交的,也就是你提交一個query,就直接執行!可以通過 set autocommit = 0 禁止自動提交 set autocommit = 1 開啟自動提交 來實現事務的處理。但要注意當用set autocommit = 0 的時候,你以后所有的sql都將作為事務處理,直到你用commit確認或 rollback結束,注意當你結束這個事務的同時也開啟了新的事務!按第一種方法只將當前的做為一個事務!MYSQL只有 INNODB和BDB類型的數據表才支持事務處理,其他的類型是不支持的!MYSQL5.0 WINXP下測試通過~ _
代碼如下
復制代碼

mysql> use test;    Database changed    mysql> CREATE TABLE `dbtest`(    -> id int(4)    -> ) TYPE=INNODB;Query OK, 0 rows affected, 1 warning (0.05 sec)

mysql> select * from dbtest -> ;Empty set (0.01 sec)
mysql> begin;Query OK, 0 rows affected (0.00 sec)
mysql> insert into dbtest values(5);Query OK, 1 row affected (0.00 sec)
mysql> insert into dbtest value(6);Query OK, 1 row affected (0.00 sec)
mysql> commit;Query OK, 0 rows affected (0.00 sec)
mysql> select * from dbtest;+------+| id |+------+| 5 || 6 |+------+2 rows in set (0.00 sec)
mysql> begin;Query OK, 0 rows affected (0.00 sec)
mysql> insert into dbtest values(7);Query OK, 1 row affected (0.00 sec)
mysql> rollback;Query OK, 0 rows affected (0.00 sec)
mysql> select * from dbtest;+------+| id |+------+| 5 || 6 |+------+2 rows in set (0.00 sec)

mysql> mysql事務處理
php代碼實現事務的處理可以通過PHP預定義類mysqli的以下方法實現。autocommit(boolean):該方法用于限定查詢結果是否自動提交,如果該方法的參數為true則自動提交,如果參數為false則關閉自動提交。MySQL數據庫默認為自動提交。rollback():利用mysqli類中的該方法可以實現事務的回滾。commit():利用該方法可以實現提交所有查詢。
代碼如下
復制代碼

<?phpinclude_once("conn.php");
$id=$_GET[id];$conn->autocommit(false);if(!$conn->query("delete from tb_sco where id='".$id."'")){ $conn->rollback();}if(!$conn->query("delete from tb_stu where id='".$id."'")){ $conn->rollback();} $conn->commit(); $conn->autocommit(true); echo "ok"?>

列二
代碼如下
復制代碼

<?phprequire('connectDB.php'); //建立數據庫連接mssql_query("BEGIN TRANSACTION DEPS02_DEL"); //開始事務$delete_dep_sql="DELETE FROM TBLDEPARTMENT WHERE DEPTID='{$_GET[deptid]}'";// echo $delete_dep_sql."
";mssql_query($delete_dep_sql); //操作數據庫// var_dump($del_result);$delete_result = mssql_query("select @@ROWCOUNT as id");$delete_info = mssql_fetch_array($delete_result);$delete_rows = $delete_info[0];// var_dump($delete_rows);mssql_free_result($delete_result);echo "<script language=javascript>";if(true){ //判斷是否回滾提交mssql_query("COMMIT TRANSACTION DEPS02_DEL"); //提交事務echo "alert('delete success!');";}else{mssql_query("ROLLBACK TRANSACTION DEPS02_DEL"); //回滾事務echo "alert('delete faile!');";}echo "</script>";mssql_close();?>

例3
MySQL的事務處理在處理實際問題中有著廣泛且重要的應用,最常見的應用如銀行轉賬業務、電子商務支付業務等等。但是,值得注意的是,MySQL的事務處理功能在MYSIAM存儲引擎中是不支持的,在InnoDB存儲引擎中是支持的。現在上傳一段代碼,作為引導認識MySQL事務處理的開始,簡單的實例,但融匯思想,相信會有很大的幫助。
代碼如下
復制代碼

<?php$conn=mysql_connect('localhost','root','yourpassword')or die(mysql_error());mysql_select_db('transaction',$conn);mysql_query('set names utf8');
//創建事務mysql_query('START TRANSACTION') or die(mysql_error());$sqlA="update A set account=account-1";if(!mysql_query($sqlA)){ mysql_query('ROLLBACK') or exit(mysql_error());//判斷當執行失敗時回滾 exit();}$sqlB="update B set account=account+1";if(!mysql_query($sqlB)){ mysql_query('ROLLBACK') or exit(mysql_error());//判斷當執行失敗時回滾 exit();}mysql_query('COMMIT')or die(mysql_error());//執行事務mysql_close($conn);?>

以上代碼可以作為模擬銀行轉賬業務的事務流程。以表A、B分別表示兩個已在銀行開戶的賬戶,當賬戶A執行轉出1元給賬戶B的操作時,如果操作執行失敗,轉出將會回滾至原始狀態,不繼續向下執行動作。反之,如果操作執行成功,則賬戶B可用余額將增加1元,否則事務回滾至原始狀態。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容