文章主要介紹了MySQL事務(wù)處理用法與實(shí)例代碼詳解,詳細(xì)的介紹了事物的特性和用法并實(shí)現(xiàn)php和mysql事務(wù)處理例子,非常具有實(shí)用價(jià)值,需要的朋友可以參考下

  MySQL的事務(wù)支持不是綁定在MySQL服務(wù)器本身,而是與存儲(chǔ)引擎相關(guān)

  1.MyISAM:不支持事務(wù),用于只讀程序提高性能

  2.InnoDB:支持ACID事務(wù)、行級(jí)鎖、并發(fā)

  3.Berkeley DB:支持事務(wù)

  一個(gè)事務(wù)是一個(gè)連續(xù)的一組數(shù)據(jù)庫(kù)操作,就好像它是一個(gè)單一的工作單元進(jìn)行。換言之,永遠(yuǎn)不會(huì)是完整的事務(wù),除非該組內(nèi)的每個(gè)單獨(dú)的操作是成功的。如果在事務(wù)的任何操作失敗,則整個(gè)事務(wù)將失敗。

  實(shí)際上,會(huì)俱樂(lè)部許多SQL查詢到一個(gè)組中,將執(zhí)行所有的人都一起作為事務(wù)的一部分。

事務(wù)的特性:

  事務(wù)有以下四個(gè)標(biāo)準(zhǔn)屬性的縮寫ACID,通常被稱為:

  原子性: 確保工作單元內(nèi)的所有操作都成功完成,否則事務(wù)將被中止在故障點(diǎn),和以前的操作將回滾到以前的狀態(tài)。

  一致性: 確保數(shù)據(jù)庫(kù)正確地改變狀態(tài)后,成功提交的事務(wù)。

  隔離性: 使事務(wù)操作彼此獨(dú)立的和透明的。

  持久性: 確保提交的事務(wù)的結(jié)果或效果的系統(tǒng)出現(xiàn)故障的情況下仍然存在。

  在MySQL中,事務(wù)開(kāi)始使用COMMIT或ROLLBACK語(yǔ)句開(kāi)始工作和結(jié)束。開(kāi)始和結(jié)束語(yǔ)句的SQL命令之間形成了大量的事務(wù)。

COMMIT & ROLLBACK:

  這兩個(gè)關(guān)鍵字提交和回滾主要用于MySQL的事務(wù)。

  當(dāng)一個(gè)成功的事務(wù)完成后,發(fā)出COMMIT命令應(yīng)使所有參與表的更改才會(huì)生效。

  如果發(fā)生故障時(shí),應(yīng)發(fā)出一個(gè)ROLLBACK命令返回的事務(wù)中引用的每一個(gè)表到以前的狀態(tài)。

  可以控制的事務(wù)行為稱為AUTOCOMMIT設(shè)置會(huì)話變量。如果AUTOCOMMIT設(shè)置為1(默認(rèn)值),然后每一個(gè)SQL語(yǔ)句(在事務(wù)與否)被認(rèn)為是一個(gè)完整的事務(wù),并承諾在默認(rèn)情況下,當(dāng)它完成。 AUTOCOMMIT設(shè)置為0時(shí),發(fā)出SET AUTOCOMMIT =0命令,在隨后的一系列語(yǔ)句的作用就像一個(gè)事務(wù),直到一個(gè)明確的COMMIT語(yǔ)句時(shí),沒(méi)有活動(dòng)的提交。

  可以通過(guò)使用mysql_query()函數(shù)在PHP中執(zhí)行這些SQL命令。

通用事務(wù)例子

  這一系列事件是獨(dú)立于所使用的編程語(yǔ)言,可以建立在任何使用的語(yǔ)言來(lái)創(chuàng)建應(yīng)用程序的邏輯路徑。

  可以通過(guò)使用mysql_query()函數(shù)在PHP中執(zhí)行這些SQL命令。

BEGIN WORK開(kāi)始事務(wù)發(fā)出SQL命令

  發(fā)出一個(gè)或多個(gè)SQL命令,如SELECT,INSERT,UPDATE或DELETE

  檢查是否有任何錯(cuò)誤,一切都依據(jù)的需要。

  如果有任何錯(cuò)誤,那么問(wèn)題ROLLBACK命令,否則發(fā)出COMMIT命令。

在MySQL中的事務(wù)安全表類型:

  如果打算使用MySQL事務(wù)編程,那么就需要一種特殊的方式創(chuàng)建表。有很多支持事務(wù)但最流行的是InnoDB表類型。

  從源代碼編譯MySQL時(shí),InnoDB表支持需要特定的編譯參數(shù)。如果MySQL版本沒(méi)有InnoDB支持,請(qǐng)互聯(lián)網(wǎng)服務(wù)提供商建立一個(gè)版本的MySQL支持InnoDB表類型,或者下載并安裝Windows或Linux/UNIX的MySQL-Max二進(jìn)制分發(fā)和使用的表類型在開(kāi)發(fā)環(huán)境中。

  如果MySQL安裝支持InnoDB表,只需添加一個(gè)的TYPE=InnoDB 定義表創(chuàng)建語(yǔ)句。例如,下面的代碼創(chuàng)建InnoDB表tcount_tbl:?

  1. root@host# mysql -u root -p password;
  2. Enter password:*******
  3. mysql> use TUTORIALS;
  4. Database changed
  5. mysql> create table tcount_tbl
  6. -> (
  7. -> tutorial_author varchar(40) NOT NULL,
  8. -> tutorial_count INT
  9. -> ) TYPE=InnoDB;
  10. Query OK, 0 rows affected (0.05 sec)

  可以使用其他GEMINI或BDB表類型,但它取決于您的安裝,如果它支持這兩種類型。

  由于項(xiàng)目設(shè)計(jì)里面,牽扯到了金錢的轉(zhuǎn)移,于是就要用到MYSQL的事務(wù)處理,來(lái)保證一組處理結(jié)果的正確性。用了事務(wù),就不可避免的要犧牲一部分速度,來(lái)保證數(shù)據(jù)的正確性。

只有InnoDB支持事務(wù)

  事務(wù) ACID Atomicity(原子性)、Consistency(穩(wěn)定性)、Isolation(隔離性)、Durability(可靠性)

  1、事務(wù)的原子性

  一組事務(wù),要么成功;要么撤回。

  2、穩(wěn)定性

  有非法數(shù)據(jù)(外鍵約束之類),事務(wù)撤回。

  3、隔離性

  事務(wù)獨(dú)立運(yùn)行。

  一個(gè)事務(wù)處理后的結(jié)果,影響了其他事務(wù),那么其他事務(wù)會(huì)撤回。

  事務(wù)的100%隔離,需要犧牲速度。

  4、可靠性

  軟、硬件崩潰后,InnoDB數(shù)據(jù)表驅(qū)動(dòng)會(huì)利用日志文件重構(gòu)修改。

  可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項(xiàng) 決定什么時(shí)候吧事務(wù)保存到日志里。

開(kāi)啟事務(wù)

  1. START TRANSACTION BEGIN

提交事務(wù)(關(guān)閉事務(wù))

  1. COMMIT

放棄事務(wù)(關(guān)閉事務(wù))

  1. ROLLBACK

折返點(diǎn)

  1. SAVEPOINT adqoo_1
  2. ROLLBACK TO SAVEPOINT adqoo_1

  發(fā)生在折返點(diǎn) adqoo_1 之前的事務(wù)被提交,之后的被忽略

事務(wù)的終止

  設(shè)置“自動(dòng)提交”模式

  SET AUTOCOMMIT = 0

  每條SQL都是同一個(gè)事務(wù)的不同命令,之間由 COMMIT 或 ROLLBACK隔開(kāi)

  掉線后,沒(méi)有 COMMIT 的事務(wù)都被放棄

事務(wù)鎖定模式

  系統(tǒng)默認(rèn): 不需要等待某事務(wù)結(jié)束,可直接查詢到結(jié)果,但不能再進(jìn)行修改、刪除。

  缺點(diǎn):查詢到的結(jié)果,可能是已經(jīng)過(guò)期的。

  優(yōu)點(diǎn):不需要等待某事務(wù)結(jié)束,可直接查詢到結(jié)果。

需要用以下模式來(lái)設(shè)定鎖定模式

1、SELECT …… LOCK IN SHARE MODE(共享鎖)

  查詢到的數(shù)據(jù),就是數(shù)據(jù)庫(kù)在這一時(shí)刻的數(shù)據(jù)(其他已commit事務(wù)的結(jié)果,已經(jīng)反應(yīng)到這里了)

  SELECT 必須等待,某個(gè)事務(wù)結(jié)束后才能執(zhí)行

2、SELECT …… FOR UPDATE(排它鎖)

  例如 SELECT * FROM tablename WHERE id<200

  那么id<200的數(shù)據(jù),被查詢到的數(shù)據(jù),都將不能再進(jìn)行修改、刪除、SELECT …… LOCK IN SHARE MODE操作

  一直到此事務(wù)結(jié)束

  共享鎖 和 排它鎖 的區(qū)別:在于是否阻斷其他客戶發(fā)出的 SELECT …… LOCK IN SHARE MODE命令

3、INSERT / UPDATE / DELETE

  所有關(guān)聯(lián)數(shù)據(jù)都會(huì)被鎖定,加上排它鎖

4、防插入鎖

  例如 SELECT * FROM tablename WHERE id>200

  那么id>200的記錄無(wú)法被插入

5、死鎖

  自動(dòng)識(shí)別死鎖

  先進(jìn)來(lái)的進(jìn)程被執(zhí)行,后來(lái)的進(jìn)程收到出錯(cuò)消息,并按ROLLBACK方式回滾

  innodb_lock_wait_timeout = n 來(lái)設(shè)置最長(zhǎng)等待時(shí)間,默認(rèn)是50秒

事務(wù)隔離模式

  SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL

  READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE

  1、不帶SESSION、GLOBAL的SET命令

  只對(duì)下一個(gè)事務(wù)有效

  2、SET SESSION

  為當(dāng)前會(huì)話設(shè)置隔離模式

  3、SET GLOBAL

  為以后新建的所有MYSQL連接設(shè)置隔離模式(當(dāng)前連接不包括在內(nèi))

  隔離模式

  READ UNCOMMITTED

  不隔離SELECT

  其他事務(wù)未完成的修改(未COMMIT),其結(jié)果也考慮在內(nèi)

  READ COMMITTED

  把其他事務(wù)的 COMMIT 修改考慮在內(nèi)

  同一個(gè)事務(wù)中,同一 SELECT 可能返回不同結(jié)果

  REPEATABLE READ(默認(rèn))

  不把其他事務(wù)的修改考慮在內(nèi),無(wú)論其他事務(wù)是否用COMMIT命令提交過(guò)

  同一個(gè)事務(wù)中,同一 SELECT 返回同一結(jié)果(前提是本事務(wù),不修改)

  SERIALIZABLE

  和REPEATABLE READ類似,給所有的SELECT都加上了 共享鎖

出錯(cuò)處理

  根據(jù)出錯(cuò)信息,執(zhí)行相應(yīng)的處理

mysql事物處理實(shí)例

MYSQL的事務(wù)處理主要有兩種方法

  1.用begin,rollback,commit來(lái)實(shí)現(xiàn)

  begin開(kāi)始一個(gè)事務(wù)

  rollback事務(wù)回滾

  commit 事務(wù)確認(rèn)

  2.直接用set來(lái)改變mysql的自動(dòng)提交模式

  mysql默認(rèn)是自動(dòng)提交的,也就是你提交一個(gè)query,就直接執(zhí)行!可以通過(guò)

  set autocommit = 0 禁止自動(dòng)提交

  set autocommit = 1 開(kāi)啟自動(dòng)提交

  來(lái)實(shí)現(xiàn)事務(wù)的處理。

  但要注意當(dāng)用set autocommit = 0 的時(shí)候,你以后所有的sql都將作為事務(wù)處理,直到你用commit確認(rèn)或 rollback結(jié)束,注意當(dāng)你結(jié)束這個(gè)事務(wù)的同時(shí)也開(kāi)啟了新的事務(wù)!按第一種方法只將當(dāng)前的做為一個(gè)事務(wù)!

  MYSQL只有 INNODB和BDB類型的數(shù)據(jù)表才支持事務(wù)處理,其他的類型是不支持的!?

  1. mysql> use test;
  2. Database changed
  3. mysql> CREATE TABLE `dbtest`(
  4. -> id int(4)
  5. -> ) TYPE=INNODB;
  6. Query OK, 0 rows affected, 1 warning (0.05 sec)
  7.  
  8. mysql> select * from dbtest
  9. -> ;
  10. Empty set (0.01 sec)
  11.  
  12. mysql> begin;
  13. Query OK, 0 rows affected (0.00 sec)
  14.  
  15. mysql> insert into dbtest values(5);
  16. Query OK, 1 row affected (0.00 sec)
  17.  
  18. mysql> insert into dbtest value(6);
  19. Query OK, 1 row affected (0.00 sec)
  20.  
  21. mysql> commit;
  22. Query OK, 0 rows affected (0.00 sec)
  23.  
  24. mysql> select * from dbtest;
  25. +------+
  26. | id |
  27. +------+
  28. | 5 |
  29. | 6 |
  30. +------+
  31. 2 rows in set (0.00 sec)
  32.  
  33. mysql> begin;
  34. Query OK, 0 rows affected (0.00 sec)
  35.  
  36. mysql> insert into dbtest values(7);
  37. Query OK, 1 row affected (0.00 sec)
  38.  
  39. mysql> rollback;
  40. Query OK, 0 rows affected (0.00 sec)
  41.  
  42. mysql> select * from dbtest;
  43. +------+
  44. | id |
  45. +------+
  46. | 5 |
  47. | 6 |
  48. +------+
  49. 2 rows in set (0.00 sec)

mysql事務(wù)處理

  php代碼實(shí)現(xiàn)事務(wù)的處理可以通過(guò)PHP預(yù)定義類mysqli的以下方法實(shí)現(xiàn)。

  autocommit(boolean):該方法用于限定查詢結(jié)果是否自動(dòng)提交,如果該方法的參數(shù)為true則自動(dòng)提交,如果參數(shù)為false則關(guān)閉自動(dòng)提交。MySQL數(shù)據(jù)庫(kù)默認(rèn)為自動(dòng)提交。

  rollback():利用mysqli類中的該方法可以實(shí)現(xiàn)事務(wù)的回滾。

  commit():利用該方法可以實(shí)現(xiàn)提交所有查詢。

  1.  <?php
  2. include_once("conn.php");
  3.  
  4. $id=$_GET[id];
  5. $conn->autocommit(false);
  6. if(!$conn->query("delete from tb_sco where id='".$id."'"))
  7. {
  8. $conn->rollback();
  9. }
  10. if(!$conn->query("delete from tb_stu where id='".$id."'"))
  11. {
  12. $conn->rollback();
  13. }
  14. $conn->commit();
  15. $conn->autocommit(true);
  16. echo "ok"
  17. ?>
  1.   <?php
  2. require('connectDB.php'); //建立數(shù)據(jù)庫(kù)連接
  3. MsSQL_query("BEGIN TRANSACTION DEPS02_DEL"); //開(kāi)始事務(wù)
  4. $delete_dep_sql="DELETE FROM TBLDEPARTMENT WHERE DEPTID='{$_GET[deptid]}'";
  5. // echo $delete_dep_sql."<br>";
  6. mssql_query($delete_dep_sql); //操作數(shù)據(jù)庫(kù)
  7. // var_dump($del_result);
  8. $delete_result = mssql_query("select @@ROWCOUNT as id");
  9. $delete_info = mssql_fetch_array($delete_result);
  10. $delete_rows = $delete_info[0];
  11. // var_dump($delete_rows);
  12. mssql_free_result($delete_result);
  13. echo "<script language=javascript>";
  14. if(true){ //判斷是否回滾提交
  15. mssql_query("COMMIT TRANSACTION DEPS02_DEL"); //提交事務(wù)
  16. echo "alert('delete success!');";
  17. }else{
  18. mssql_query("ROLLBACK TRANSACTION DEPS02_DEL"); //回滾事務(wù)
  19. echo "alert('delete faile!');";
  20. }
  21. echo "</script>";mssql_close();
  22. ?>

  MySQL的事務(wù)處理在處理實(shí)際問(wèn)題中有著廣泛且重要的應(yīng)用,最常見(jiàn)的應(yīng)用如銀行轉(zhuǎn)賬業(yè)務(wù)、電子商務(wù)支付業(yè)務(wù)等等。但是,值得注意的是,MySQL的事務(wù)處理功能在MYSIAM存儲(chǔ)引擎中是不支持的,在InnoDB存儲(chǔ)引擎中是支持的。現(xiàn)在上傳一段代碼,作為引導(dǎo)認(rèn)識(shí)MySQL事務(wù)處理的開(kāi)始,簡(jiǎn)單的實(shí)例,但融匯思想,相信會(huì)有很大的幫助。?

  1. <?php
  2. $conn=mysql_connect('localhost','root','yourpassword')or die(mysql_error());
  3. mysql_select_db('transaction',$conn);
  4. mysql_query('set names utf8');
  5.  
  6. //創(chuàng)建事務(wù)
  7. mysql_query('START TRANSACTION') or die(mysql_error());
  8. $sqlA="update A set account=account-1";
  9. if(!mysql_query($sqlA)){
  10. mysql_query('ROLLBACK') or exit(mysql_error());//判斷當(dāng)執(zhí)行失敗時(shí)回滾
  11. exit();
  12. }
  13. $sqlB="update B set account=account+1";
  14. if(!mysql_query($sqlB)){
  15. mysql_query('ROLLBACK') or exit(mysql_error());//判斷當(dāng)執(zhí)行失敗時(shí)回滾
  16. exit();
  17. }
  18. mysql_query('COMMIT')or die(mysql_error());//執(zhí)行事務(wù)
  19. mysql_close($conn);
  20. ?>

  以上代碼可以作為模擬銀行轉(zhuǎn)賬業(yè)務(wù)的事務(wù)流程。以表A、B分別表示兩個(gè)已在銀行開(kāi)戶的賬戶,當(dāng)賬戶A執(zhí)行轉(zhuǎn)出1元給賬戶B的操作時(shí),如果操作執(zhí)行失敗,轉(zhuǎn)出將會(huì)回滾至原始狀態(tài),不繼續(xù)向下執(zhí)行動(dòng)作。反之,如果操作執(zhí)行成功,則賬戶B可用余額將增加1元,否則事務(wù)回滾至原始狀態(tài)。