來源轉(zhuǎn)載自:http://www.cnblogs.com/ymy124/p/3718439.html
MySQL的事務(wù)支持不是綁定在MySQL服務(wù)器本身姨伤,而是與存儲引擎相關(guān)1.MyISAM:不支持事務(wù)哨坪,用于只讀程序提高性能 2.InnoDB:支持ACID事務(wù)、行級鎖乍楚、并發(fā) 3.Berkeley DB:支持事務(wù)
一個事務(wù)是一個連續(xù)的一組數(shù)據(jù)庫操作当编,就好像它是一個單一的工作單元進行。換言之徒溪,永遠不會是完整的事務(wù)忿偷,除非該組內(nèi)的每個單獨的操作是成功的。如果在事務(wù)的任何操作失敗臊泌,則整個事務(wù)將失敗鲤桥。
實際上,會俱樂部許多SQL查詢到一個組中渠概,將執(zhí)行所有的人都一起作為事務(wù)的一部分茶凳。
事務(wù)的特性: 事務(wù)有以下四個標(biāo)準(zhǔn)屬性的縮寫ACID,通常被稱為:
原子性: 確保工作單元內(nèi)的所有操作都成功完成播揪,否則事務(wù)將被中止在故障點慧妄,和以前的操作將回滾到以前的狀態(tài)。
一致性: 確保數(shù)據(jù)庫正確地改變狀態(tài)后剪芍,成功提交的事務(wù)塞淹。
隔離性: 使事務(wù)操作彼此獨立的和透明的。
持久性: 確保提交的事務(wù)的結(jié)果或效果的系統(tǒng)出現(xiàn)故障的情況下仍然存在罪裹。
在MySQL中饱普,事務(wù)開始使用COMMIT或ROLLBACK語句開始工作和結(jié)束运挫。開始和結(jié)束語句的SQL命令之間形成了大量的事務(wù)。
COMMIT & ROLLBACK: 這兩個關(guān)鍵字提交和回滾主要用于MySQL的事務(wù)套耕。
當(dāng)一個成功的事務(wù)完成后谁帕,發(fā)出COMMIT命令應(yīng)使所有參與表的更改才會生效。
如果發(fā)生故障時冯袍,應(yīng)發(fā)出一個ROLLBACK命令返回的事務(wù)中引用的每一個表到以前的狀態(tài)匈挖。
可以控制的事務(wù)行為稱為AUTOCOMMIT設(shè)置會話變量。如果AUTOCOMMIT設(shè)置為1(默認值)康愤,然后每一個SQL語句(在事務(wù)與否)被認為是一個完整的事務(wù)儡循,并承諾在默認情況下,當(dāng)它完成征冷。 AUTOCOMMIT設(shè)置為0時择膝,發(fā)出SET AUTOCOMMIT =0命令,在隨后的一系列語句的作用就像一個事務(wù)检激,直到一個明確的COMMIT語句時肴捉,沒有活動的提交。
可以通過使用mysql_query()函數(shù)在PHP中執(zhí)行這些SQL命令叔收。
通用事務(wù)例子 這一系列事件是獨立于所使用的編程語言齿穗,可以建立在任何使用的語言來創(chuàng)建應(yīng)用程序的邏輯路徑〗嚷桑可以通過使用mysql_query()函數(shù)在PHP中執(zhí)行這些SQL命令缤灵。
BEGIN WORK開始事務(wù)發(fā)出SQL命令
發(fā)出一個或多個SQL命令,如SELECT蓝晒,INSERT腮出,UPDATE或DELETE
檢查是否有任何錯誤,一切都依據(jù)的需要芝薇。
如果有任何錯誤胚嘲,那么問題ROLLBACK命令,否則發(fā)出COMMIT命令洛二。
在MySQL中的事務(wù)安全表類型:
如果打算使用MySQL事務(wù)編程馋劈,那么就需要一種特殊的方式創(chuàng)建表。有很多支持事務(wù)但最流行的是InnoDB表類型晾嘶。
從源代碼編譯MySQL時妓雾,InnoDB表支持需要特定的編譯參數(shù)。如果MySQL版本沒有InnoDB支持垒迂,請互聯(lián)網(wǎng)服務(wù)提供商建立一個版本的MySQL支持InnoDB表類型械姻,或者下載并安裝Windows或Linux/UNIX的MySQL-Max二進制分發(fā)和使用的表類型在開發(fā)環(huán)境中。如果MySQL安裝支持InnoDB表机断,只需添加一個的TYPE=InnoDB 定義表創(chuàng)建語句楷拳。例如绣夺,下面的代碼創(chuàng)建InnoDB表tcount_tbl:
代碼如下
復(fù)制代碼
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表類型,但它取決于您的安裝欢揖,如果它支持這兩種類型陶耍。
由于項目設(shè)計里面,牽扯到了金錢的轉(zhuǎn)移她混,于是就要用到MYSQL的事務(wù)處理烈钞,來保證一組處理結(jié)果的正確性。用了事務(wù)坤按,就不可避免的要犧牲一部分速度毯欣,來保證數(shù)據(jù)的正確性。只有InnoDB支持事務(wù)
事務(wù) ACID Atomicity(原子性)晋涣、Consistency(穩(wěn)定性)、Isolation(隔離性)沉桌、Durability(可靠性)
1谢鹊、事務(wù)的原子性一組事務(wù),要么成功留凭;要么撤回佃扼。
2、穩(wěn)定性有非法數(shù)據(jù)(外鍵約束之類)蔼夜,事務(wù)撤回兼耀。
3、隔離性事務(wù)獨立運行求冷。一個事務(wù)處理后的結(jié)果瘤运,影響了其他事務(wù),那么其他事務(wù)會撤回匠题。事務(wù)的100%隔離拯坟,需要犧牲速度。
4韭山、可靠性軟郁季、硬件崩潰后,InnoDB數(shù)據(jù)表驅(qū)動會利用日志文件重構(gòu)修改钱磅∶瘟眩可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項 決定什么時候吧事務(wù)保存到日志里盖淡。開啟事務(wù)START TRANSACTION 或 BEGIN
提交事務(wù)(關(guān)閉事務(wù))COMMIT
放棄事務(wù)(關(guān)閉事務(wù))ROLLBACK
折返點SAVEPOINT adqoo_1ROLLBACK TO SAVEPOINT adqoo_1發(fā)生在折返點 adqoo_1 之前的事務(wù)被提交年柠,之后的被忽略
事務(wù)的終止
設(shè)置“自動提交”模式SET AUTOCOMMIT = 0每條SQL都是同一個事務(wù)的不同命令,之間由 COMMIT 或 ROLLBACK隔開掉線后褪迟,沒有 COMMIT 的事務(wù)都被放棄
事務(wù)鎖定模式
系統(tǒng)默認: 不需要等待某事務(wù)結(jié)束彪杉,可直接查詢到結(jié)果毅往,但不能再進行修改、刪除派近。缺點:查詢到的結(jié)果攀唯,可能是已經(jīng)過期的。優(yōu)點:不需要等待某事務(wù)結(jié)束渴丸,可直接查詢到結(jié)果侯嘀。
需要用以下模式來設(shè)定鎖定模式
1、SELECT …… LOCK IN SHARE MODE(共享鎖)查詢到的數(shù)據(jù)谱轨,就是數(shù)據(jù)庫在這一時刻的數(shù)據(jù)(其他已commit事務(wù)的結(jié)果戒幔,已經(jīng)反應(yīng)到這里了)SELECT 必須等待,某個事務(wù)結(jié)束后才能執(zhí)行
2土童、SELECT …… FOR UPDATE(排它鎖)例如 SELECT * FROM tablename WHERE id<200那么id<200的數(shù)據(jù)诗茎,被查詢到的數(shù)據(jù),都將不能再進行修改献汗、刪除敢订、SELECT …… LOCK IN SHARE MODE操作一直到此事務(wù)結(jié)束
共享鎖 和 排它鎖 的區(qū)別:在于是否阻斷其他客戶發(fā)出的 SELECT …… LOCK IN SHARE MODE命令
3、INSERT / UPDATE / DELETE所有關(guān)聯(lián)數(shù)據(jù)都會被鎖定罢吃,加上排它鎖
4楚午、防插入鎖例如 SELECT * FROM tablename WHERE id>200那么id>200的記錄無法被插入
5、死鎖自動識別死鎖先進來的進程被執(zhí)行尿招,后來的進程收到出錯消息矾柜,并按ROLLBACK方式回滾innodb_lock_wait_timeout = n 來設(shè)置最長等待時間,默認是50秒
事務(wù)隔離模式
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVELREAD UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE1就谜、不帶SESSION怪蔑、GLOBAL的SET命令只對下一個事務(wù)有效2、SET SESSION為當(dāng)前會話設(shè)置隔離模式3丧荐、SET GLOBAL為以后新建的所有MYSQL連接設(shè)置隔離模式(當(dāng)前連接不包括在內(nèi))
隔離模式
READ UNCOMMITTED不隔離SELECT其他事務(wù)未完成的修改(未COMMIT)饮睬,其結(jié)果也考慮在內(nèi)
READ COMMITTED把其他事務(wù)的 COMMIT 修改考慮在內(nèi)同一個事務(wù)中,同一 SELECT 可能返回不同結(jié)果
REPEATABLE READ(默認)不把其他事務(wù)的修改考慮在內(nèi)篮奄,無論其他事務(wù)是否用COMMIT命令提交過同一個事務(wù)中捆愁,同一 SELECT 返回同一結(jié)果(前提是本事務(wù),不修改)
SERIALIZABLE和REPEATABLE READ類似窟却,給所有的SELECT都加上了 共享鎖
出錯處理根據(jù)出錯信息昼丑,執(zhí)行相應(yīng)的處理
mysql事物處理實例
MYSQL的事務(wù)處理主要有兩種方法1.用begin,rollback,commit來實現(xiàn) begin開始一個事務(wù) rollback事務(wù)回滾 commit 事務(wù)確認2.直接用set來改變mysql的自動提交模式 mysql默認是自動提交的,也就是你提交一個query夸赫,就直接執(zhí)行菩帝!可以通過 set autocommit = 0 禁止自動提交 set autocommit = 1 開啟自動提交 來實現(xiàn)事務(wù)的處理。但要注意當(dāng)用set autocommit = 0 的時候,你以后所有的sql都將作為事務(wù)處理呼奢,直到你用commit確認或 rollback結(jié)束宜雀,注意當(dāng)你結(jié)束這個事務(wù)的同時也開啟了新的事務(wù)!按第一種方法只將當(dāng)前的做為一個事務(wù)!MYSQL只有 INNODB和BDB類型的數(shù)據(jù)表才支持事務(wù)處理握础,其他的類型是不支持的!MYSQL5.0 WINXP下測試通過~ _
代碼如下
復(fù)制代碼
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事務(wù)處理
php代碼實現(xiàn)事務(wù)的處理可以通過PHP預(yù)定義類mysqli的以下方法實現(xiàn)辐董。autocommit(boolean):該方法用于限定查詢結(jié)果是否自動提交,如果該方法的參數(shù)為true則自動提交禀综,如果參數(shù)為false則關(guān)閉自動提交简烘。MySQL數(shù)據(jù)庫默認為自動提交。rollback():利用mysqli類中的該方法可以實現(xiàn)事務(wù)的回滾定枷。commit():利用該方法可以實現(xiàn)提交所有查詢孤澎。
代碼如下
復(fù)制代碼
<?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"?>
列二
代碼如下
復(fù)制代碼
<?phprequire('connectDB.php'); //建立數(shù)據(jù)庫連接mssql_query("BEGIN TRANSACTION DEPS02_DEL"); //開始事務(wù)$delete_dep_sql="DELETE FROM TBLDEPARTMENT WHERE DEPTID='{$_GET[deptid]}'";// echo $delete_dep_sql."
";mssql_query($delete_dep_sql); //操作數(shù)據(jù)庫// 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"); //提交事務(wù)echo "alert('delete success!');";}else{mssql_query("ROLLBACK TRANSACTION DEPS02_DEL"); //回滾事務(wù)echo "alert('delete faile!');";}echo "</script>";mssql_close();?>
例3
MySQL的事務(wù)處理在處理實際問題中有著廣泛且重要的應(yīng)用,最常見的應(yīng)用如銀行轉(zhuǎn)賬業(yè)務(wù)欠窒、電子商務(wù)支付業(yè)務(wù)等等覆旭。但是,值得注意的是岖妄,MySQL的事務(wù)處理功能在MYSIAM存儲引擎中是不支持的型将,在InnoDB存儲引擎中是支持的。現(xiàn)在上傳一段代碼衣吠,作為引導(dǎo)認識MySQL事務(wù)處理的開始茶敏,簡單的實例壤靶,但融匯思想缚俏,相信會有很大的幫助。
代碼如下
復(fù)制代碼
<?php$conn=mysql_connect('localhost','root','yourpassword')or die(mysql_error());mysql_select_db('transaction',$conn);mysql_query('set names utf8');
//創(chuàng)建事務(wù)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());//判斷當(dāng)執(zhí)行失敗時回滾 exit();}$sqlB="update B set account=account+1";if(!mysql_query($sqlB)){ mysql_query('ROLLBACK') or exit(mysql_error());//判斷當(dāng)執(zhí)行失敗時回滾 exit();}mysql_query('COMMIT')or die(mysql_error());//執(zhí)行事務(wù)mysql_close($conn);?>
以上代碼可以作為模擬銀行轉(zhuǎn)賬業(yè)務(wù)的事務(wù)流程贮乳。以表A忧换、B分別表示兩個已在銀行開戶的賬戶,當(dāng)賬戶A執(zhí)行轉(zhuǎn)出1元給賬戶B的操作時向拆,如果操作執(zhí)行失敗亚茬,轉(zhuǎn)出將會回滾至原始狀態(tài),不繼續(xù)向下執(zhí)行動作浓恳。反之刹缝,如果操作執(zhí)行成功,則賬戶B可用余額將增加1元颈将,否則事務(wù)回滾至原始狀態(tài)梢夯。