国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

mysql事務回滾使用與常見問題介紹

2024-07-24 12:38:07
字體:
來源:轉載
供稿:網友

MYSQL中只有INNODB和BDB類型的數據表才能支持事務處理,其他的類型是不支持的! ***:一般MYSQL數據庫默認的引擎是MyISAM,這種引擎不支持事務,如果要讓MYSQL支持事務,可以自己手動修改.

方法如下:

1.修改c:appservmysqlmy.ini文件,找到skip-InnoDB,在前面加上#,后保存文件。

2.在運行中輸入:services.msc,重啟mysql服務。

3.到phpmyadmin中,mysql->show engines;(或執行mysql->show variables like 'have_%'; ),查看InnoDB為YES,即表示數據庫支持InnoDB了,也就說明支持事務transaction了.

4.在創建表時,就可以為Storage Engine選擇InnoDB引擎了,如果是以前創建的表,可以使用如下代碼:

  1. mysql->alter table table_name type=InnoDB; 
  2. --或  
  3. mysql->alter table table_name engine=InnoDB; 

來改變數據表的引擎以支持事務.

事務回滾在事務中,每個正確的原子操作都會被順序執行,直到遇到錯誤的原子操作,此時事務會將之前的操作進行回滾,回滾的意思是如果之前是插入操作,那么會執行刪除插入的記錄,如果之前是update操作,也會執行update操作將之前的記錄還原,因此,正確的原子操作是真正被執行過的.

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結束.

注意當你結束這個事務的同時也開啟了個新的事務,按第一種方法只將當前的作為一個事務!

PHP實現MySQL事務回滾,創建一個測試的數據庫,代碼如下:

  1. mysql> CREATE DATABASE `shop_test` DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; 
  2. Query OK, 1 row affected (0.00 sec) 
  3.  
  4. mysql> use shop_test; 
  5. Database changed 
  6.  
  7. mysql> CREATE TABLE IF NOT EXISTS `user_account`( 
  8.     -> `uservarchar(20) NOT NULL
  9.     -> `money` INT(10) NOT NULL
  10.     -> PRIMARY KEY (`user`) 
  11.     -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; 
  12. Query OK, 0 rows affected (0.51 sec) 
  13.  
  14. mysql> CREATE TABLE IF NOT EXISTS `user_order`( 
  15.     -> `id` INT(10) NOT NULL
  16.     -> `userVARCHAR(20) NOT NULL
  17.     -> `price` INT(10) NOT NULL
  18.     -> `countINT(10) NOT NULL
  19.     -> PRIMARY KEY (`id`) 
  20.     -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1; 
  21. Query OK, 0 rows affected (0.33 sec) 
  22.  
  23. mysql> INSERT INTO `user_account` VALUES ('luchanghong''100'); 
  24. Query OK, 1 row affected (0.00 sec)  

PHP測試代碼:

  1. $conn = mysql_connect('127.0.0.1''root''root'); 
  2. mysql_select_db('shop_test'); 
  3. mysql_query('SET NAMES UTF8'); 
  4.  
  5. # start transaction 
  6. mysql_query("START TRANSACTION"); 
  7. $sql = "INSERT INTO `user_order` VALUES ('1', 'luchanghong', '10', '2')"
  8. mysql_query($sql); 
  9. $sql_2 = "UPDATE `user_account` SET `money` = `money` - 10*2 WHERE `user` = 'luchanghong'"
  10. mysql_query($sql_2); 
  11. //Vevb.com 
  12. if (mysql_errno()){ 
  13.     echo "error"
  14.     mysql_query("ROLLBACK"); 
  15. }else
  16.     echo "OK"
  17.     mysql_query("COMMIT"); 

執行一次后查看數據庫,代碼如下:

  1. mysql> SELECT * FROM `user_account`; 
  2. +-------------+-------+ 
  3. user        | money | 
  4. +-------------+-------+ 
  5. | luchanghong |    80 | 
  6. +-------------+-------+ 
  7. 1 row in set (0.00 sec) 
  8.  
  9. mysql> SELECT * FROM `user_order`; 
  10. +----+-------------+-------+-------+ 
  11. | id | user        | price | count | 
  12. +----+-------------+-------+-------+ 
  13. |  1 | luchanghong |    10 |     2 | 
  14. +----+-------------+-------+-------+ 
  15. 1 row in set (0.00 sec) 

那么,我添加一個條件,就是每次更新完 user_account 表后檢查用戶的 money 是否為負值,如果為負值那么就要撤銷之前的操作,執行事務回滾,代碼如下:

  1. $conn = mysql_connect('127.0.0.1''root''root'); 
  2. mysql_select_db('shop_test'); 
  3. mysql_query('SET NAMES UTF8'); 
  4.  
  5. // start transaction 
  6. mysql_query("START TRANSACTION"); 
  7. $sql = "INSERT INTO `user_order`(`user`, `price`, `count`) VALUES ('luchanghong', '10', '2')"
  8. mysql_query($sql); 
  9. $sql_2 = "UPDATE `user_account` SET `money` = `money` - 10*2 WHERE `user` = 'luchanghong'"
  10. mysql_query($sql_2); 
  11.  
  12. if (mysql_errno()){ 
  13.     echo "error n"
  14.     mysql_query("ROLLBACK"); 
  15. }else
  16.     $money = check_remain_money('luchanghong'); 
  17.     echo $money." "
  18.     if ($money < 0){  
  19.         echo "No enough money n"
  20.         mysql_query("ROLLBACK"); 
  21.     }else
  22.         echo "OK n"
  23.         mysql_query("COMMIT"); 
  24.     }    
  25.  
  26. function check_remain_money($user){ 
  27.     $sql = "SELECT `money` FROM `user_account` WHERE `user` = '{$user}'"
  28.     $result = mysql_fetch_assoc( mysql_query($sql) ); 
  29.     return !emptyempty($result) ? $result['money'] : 0; 

接著,在shell下多次執行這php文件,WIN下就手動執行幾次吧,代碼如下:

  1. lch@LCH:~/Desktop $ for x in `seq 6`; do php transaction.php ; done 
  2. 60 OK  
  3. 40 OK  
  4. 20 OK  
  5. 0 OK  
  6. -20 No enough money  
  7. -20 No enough money 

再看數據庫數據,代碼如下:

  1. mysql> SELECT * FROM `user_account`; 
  2. +-------------+-------+ 
  3. user        | money | 
  4. +-------------+-------+ 
  5. | luchanghong |     0 | 
  6. +-------------+-------+ 
  7. 1 row in set (0.00 sec) 
  8.  
  9. mysql> SELECT * FROM `user_order`; 
  10. +----+-------------+-------+-------+ 
  11. | id | user        | price | count | 
  12. +----+-------------+-------+-------+ 
  13. |  1 | luchanghong |    10 |     2 | 
  14. |  2 | luchanghong |    10 |     2 | 
  15. |  3 | luchanghong |    10 |     2 | 
  16. |  4 | luchanghong |    10 |     2 | 
  17. |  5 | luchanghong |    10 |     2 | 
  18. +----+-------------+-------+-------+ 
  19. rows in set (0.00 sec) 

1、為什么auto_increament沒有回滾?

因為innodb的auto_increament的計數器記錄的當前值是保存在存內 存中的,并不是存在于磁盤上,當mysql server處于運行的時候,這個計數值只會隨著insert改增長,不會隨著delete而減少。而當mysql server啟動時,當我們需要去查詢auto_increment計數值時,mysql便會自動執行:SELECT MAX(id) FROM 表名 FOR UPDATE;語句來獲得當前auto_increment列的最大值,然后將這個值放到auto_increment計數器中。所以就算 Rollback MySQL的auto_increament計數器也不會作負運算。

2、MySQL的事務對表操作的時候是否是物理操作?

MySQL的事務是有redo和undo的,redo操作的所有信息都是記錄到 redo_log中,也就是說當一個事務做commit操作時,需要先把這個事務的操作寫到redo_log中,然后再把這些操作flush到磁盤上,當 出現故障時,只需要讀取redo_log,然后再重新flush到磁盤就行了.

而對于undo就比較麻煩,MySQL在處理事務時,會在數據共享 表空間里申請一個段叫做segment段,用保存undo信息,當在處理rollback,不是完完全全的物理undo,而是邏輯undo,就是說會對之 前的操作進行反操作,但是這些共享表空間是不進行回收的,這些表空間的回收需要由mysql的master thread進程來進行回收.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广河县| 邯郸市| 德格县| 安新县| 宜州市| 兴城市| 山阴县| 江油市| 建始县| 尤溪县| 通辽市| 长宁区| 错那县| 叙永县| 沭阳县| 张家川| 漳州市| 宜黄县| 尉氏县| 龙游县| 太和县| 白山市| 宁德市| 宣恩县| 麻栗坡县| 五寨县| 天峨县| 若尔盖县| 宝兴县| 礼泉县| 宜兰市| 洪雅县| 汾西县| 尉氏县| 长兴县| 宣恩县| 荔浦县| 长兴县| 金堂县| 绥滨县| 富民县|