來源轉載自: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元,否則事務回滾至原始狀態。