MySQL事务和隔离级别

理论部分:

事务是什么:多个操作当成一个处理单元来对待,要么同时执行,要么都不执行
事务的好处:并发执行
    1、提高吞吐量和资源利用率
    2、减少等待时间    
事务的缺点:事务是可以进行同时执行的,如果两个事务同时操作了一张表就可能产生交互    
如果A账户有3000块,B账户有两千块,A和B加起来一共有5000块
正常的事务:A转账500到B那么A和B都有了2500块,A和B加起来一共有5000块
不正常的事务:A转账500到B账户的过程中,如果有第二个事务进行计算了A和B两个事务的总和,A和B加起来一共有4500块。                    
如果A账户在减去500的时候B还没有加上,这个时候第二个事务启动了他计算了A+B=4500,并且在4500的基础上面做了一些统计更新了另外一个事务,这个时候就麻烦了,如果想解决这种情况的发生需要隔离事务。

如果想减少事务交互带来的影响,就需要使用隔离

隔离:
  隔离级别:MySQL模式隔离级别是REPATABLE READ(可重读)
           READ UNCOMMITTED:读未提交(读别人尚未提交的数据)    隔离级别最低  
           如果用户A删除一行数据,B用户马上可以看到数据被删除,B写入一行数据,A也马上可以看到
           
        READ COMMITTED:读提交(读别人已经提交的数据)
          如果A用户进行删除操作,B用户进行查看操作,那么B如果在A操作没有提交前进行过一次查看操作,数据是存在的,但是A提交之后,B在查看数据是不存在的(容易产生幻读)
        REPATABLE READ:可重读  隔离级别高
           不管A进行的是什么操作,B在事务开始和结束时看到的数据都是一样的
            如果B进行操作之前表有30行,B添加了10行,那么B执行完成操作,表应该有40行,可以在B执行的过程中A删除了20行,那么B执行完成后,查看数据只有20行(还是会产生幻读)
        SERIABLIZABLE:可串行,A用户执行的时候上锁,B用户就不能执行,如果B想执行就只能等A用户放开锁
注意:如果对并发处理的要求不是很高,可以调低隔离级别,这样性能会提高性能


操作部分:
查看默认的隔离级别
mysql> SHOW GLOBAL VARIABLES LIKE ‘%iso%‘;
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

修改隔离级别的值
mysql> SET tx_isolation=‘READ-UNCOMMITTED‘;
mysql> SELECT @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+

事务的执行:
START TANSACTION:启动事务
    SQL
    SQL
COMMIT: 提交事务
ROLLBACK: 回滚事务



例:如果启动一个事务,在事务中删除了数据,但是没有提交事务,而是选择回滚了事务,那么删除操作就会撤销
mysql> START TRANSACTION;  #启动一个事务
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM tutors;
+-----+--------------+--------+------+
| TID | Tname        | Gender | Age  |
+-----+--------------+--------+------+
|   1 | HongQigong   | M      |   93 |
|   2 | HuangYaoshi  | M      |   63 |
|   3 | Miejueshitai | F      |   72 |
|   4 | OuYangfeng   | M      |   76 |
|   5 | YiDeng       | M      |   90 |
|   6 | YuCanghai    | M      |   56 |
|   7 | Jinlunfawang | M      |   67 |
|   8 | HuYidao      | M      |   42 |
|   9 | NingZhongze  | F      |   49 |
|  10 | jerry        | M      |   50 |
+-----+--------------+--------+------+
10 rows in set (0.01 sec)

mysql> DELETE FROM tutors WHERE Tname LIKE ‘H%‘; #删除H开头的用户
Query OK, 3 rows affected (0.01 sec)

mysql> SELECT * FROM tutors;                     #查看用户已经被删除
+-----+--------------+--------+------+
| TID | Tname        | Gender | Age  |
+-----+--------------+--------+------+
|   3 | Miejueshitai | F      |   72 |
|   4 | OuYangfeng   | M      |   76 |
|   5 | YiDeng       | M      |   90 |
|   6 | YuCanghai    | M      |   56 |
|   7 | Jinlunfawang | M      |   67 |
|   9 | NingZhongze  | F      |   49 |
|  10 | jerry        | M      |   50 |
+-----+--------------+--------+------+
7 rows in set (0.00 sec)

mysql> ROLLBACK;   #回滚事务          
Query OK, 0 rows affected (0.03 sec)

mysql> SELECT * FROM tutors;    #回滚后发现删除的用户还在
+-----+--------------+--------+------+
| TID | Tname        | Gender | Age  |
+-----+--------------+--------+------+
|   1 | HongQigong   | M      |   93 |
|   2 | HuangYaoshi  | M      |   63 |
|   3 | Miejueshitai | F      |   72 |
|   4 | OuYangfeng   | M      |   76 |
|   5 | YiDeng       | M      |   90 |
|   6 | YuCanghai    | M      |   56 |
|   7 | Jinlunfawang | M      |   67 |
|   8 | HuYidao      | M      |   42 |
|   9 | NingZhongze  | F      |   49 |
|  10 | jerry        | M      |   50 |
+-----+--------------+--------+------+



但是如果在事务启动中执行了事务的提交那么,数据就不存在了
事务的提交
mysql> START TRANSACTION;                       #启动事务
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM tutors WHERE Tname LIKE ‘H%‘; #删除H开头的用户名
Query OK, 3 rows affected (0.00 sec)

mysql> COMMIT;      #提交事务
Query OK, 0 rows affected (0.04 sec)       #用户不在了

mysql> SELECT * FROM tutors;                    
+-----+--------------+--------+------+
| TID | Tname        | Gender | Age  |
+-----+--------------+--------+------+
|   3 | Miejueshitai | F      |   72 |
|   4 | OuYangfeng   | M      |   76 |
|   5 | YiDeng       | M      |   90 |
|   6 | YuCanghai    | M      |   56 |
|   7 | Jinlunfawang | M      |   67 |
|   9 | NingZhongze  | F      |   49 |
|  10 | jerry        | M      |   50 |
+-----+--------------+--------+------+


MySQL是否自动提交事务,如果没有明确启动事务,那么是自动提交MySQL语句的
mysql> SELECT @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+


建议:在支持事务的引擎上,明确使用事务,并且关闭自动提交
关闭自动提交后,在执行语句的时候,如果不启动事务,那么所有的操作就会当成一个事务来进行处理



关闭自动提交
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+

验证是否关闭了事务的自动提交
查看是否关闭事务自动提交                    
mysql> SELECT * FROM students;   #查看表的数据
+-----+--------------+------+--------+------+------+------+---------------------+
| SID | Name         | Age  | Gender | CID1 | CID2 | TID  | CreateTime          |
+-----+--------------+------+--------+------+------+------+---------------------+
|   1 | GuoJing      |   19 | M      |    2 |    7 |    3 | 2012-04-06 10:00:00 |
|   2 | YangGuo      |   17 | M      |    2 |    3 |    1 | 2012-04-06 10:00:00 |
|   3 | DingDian     |   25 | M      |    6 |    1 |    7 | 2012-04-06 10:00:00 |
|   4 | HuFei        |   31 | M      |    8 |   10 |    5 | 2012-04-06 10:00:00 |
|   5 | HuangRong    |   16 | F      |    5 |    9 |    9 | 2012-04-06 10:00:00 |
|   6 | YueLingshang |   18 | F      |    8 |    4 | NULL | 2012-04-06 10:00:00 |
|   7 | ZhangWuji    |   20 | M      |    1 |    7 | NULL | 2012-04-06 10:00:00 |
|   8 | Xuzhu        |   26 | M      |    2 |    4 | NULL | 2012-04-06 10:00:00 |
|   9 | LingHuchong  |   22 | M      |   11 | NULL | NULL | 2012-04-06 10:00:00 |
|  10 | YiLin        |   19 | F      |   18 | NULL | NULL | 2012-04-06 10:00:00 |
+-----+--------------+------+--------+------+------+------+---------------------+
10 rows in set (0.00 sec)

mysql> DELETE FROM tutors WHERE Tname=‘GuoJing‘;   #删除用户GuoJing
Query OK, 0 rows affected (0.00 sec)

mysql> ROLLBACK;                                  #回滚事务
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM students;                  #用户没有删除
+-----+--------------+------+--------+------+------+------+---------------------+
| SID | Name         | Age  | Gender | CID1 | CID2 | TID  | CreateTime          |
+-----+--------------+------+--------+------+------+------+---------------------+
|   1 | GuoJing      |   19 | M      |    2 |    7 |    3 | 2012-04-06 10:00:00 |
|   2 | YangGuo      |   17 | M      |    2 |    3 |    1 | 2012-04-06 10:00:00 |
|   3 | DingDian     |   25 | M      |    6 |    1 |    7 | 2012-04-06 10:00:00 |
|   4 | HuFei        |   31 | M      |    8 |   10 |    5 | 2012-04-06 10:00:00 |
|   5 | HuangRong    |   16 | F      |    5 |    9 |    9 | 2012-04-06 10:00:00 |
|   6 | YueLingshang |   18 | F      |    8 |    4 | NULL | 2012-04-06 10:00:00 |
|   7 | ZhangWuji    |   20 | M      |    1 |    7 | NULL | 2012-04-06 10:00:00 |
|   8 | Xuzhu        |   26 | M      |    2 |    4 | NULL | 2012-04-06 10:00:00 |
|   9 | LingHuchong  |   22 | M      |   11 | NULL | NULL | 2012-04-06 10:00:00 |
|  10 | YiLin        |   19 | F      |   18 | NULL | NULL | 2012-04-06 10:00:00 |
+-----+--------------+------+--------+------+------+------+---------------------+
10 rows in set (0.00 sec)            


事务支持保存点,如果执行100个事务,执行到85个的时候,发现执行的75个操作错了,如果这个时候进行撤销,那么所有的操作都撤销了                
可以执行10个操作记录一次保存点,如果发现75个操作错了,可以回到70个操作,那么前面的70次操作还是有的。

保存点:SAVEPOINT 保存点名
回滚至保存点:ROLLBACK TO 保存点名

mysql> SELECT * FROM students;   #查看数据
+-----+--------------+------+--------+------+------+------+---------------------+
| SID | Name         | Age  | Gender | CID1 | CID2 | TID  | CreateTime          |
+-----+--------------+------+--------+------+------+------+---------------------+
|   1 | GuoJing      |   19 | M      |    2 |    7 |    3 | 2012-04-06 10:00:00 |
|   2 | YangGuo      |   17 | M      |    2 |    3 |    1 | 2012-04-06 10:00:00 |
|   3 | DingDian     |   25 | M      |    6 |    1 |    7 | 2012-04-06 10:00:00 |
|   4 | HuFei        |   31 | M      |    8 |   10 |    5 | 2012-04-06 10:00:00 |
|   5 | HuangRong    |   16 | F      |    5 |    9 |    9 | 2012-04-06 10:00:00 |
|   6 | YueLingshang |   18 | F      |    8 |    4 | NULL | 2012-04-06 10:00:00 |
|   7 | ZhangWuji    |   20 | M      |    1 |    7 | NULL | 2012-04-06 10:00:00 |
|   8 | Xuzhu        |   26 | M      |    2 |    4 | NULL | 2012-04-06 10:00:00 |
|   9 | LingHuchong  |   22 | M      |   11 | NULL | NULL | 2012-04-06 10:00:00 |
|  10 | YiLin        |   19 | F      |   18 | NULL | NULL | 2012-04-06 10:00:00 |
+-----+--------------+------+--------+------+------+------+---------------------+
10 rows in set (0.00 sec)

mysql> START TRANSACTION;   #启动一个事务
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM students WHERE SID=10;  #删除SID=10的那一行
Query OK, 1 row affected (0.00 sec)

mysql> SAVEPOINT a;   #记录保存点a
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM students WHERE SID=9;  #删除SID=9的那一行
Query OK, 1 row affected (0.00 sec)

mysql> SAVEPOINT b;                     #记录保存点b
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM students WHERE SID=8;  #删除SID=8的那一行
Query OK, 1 row affected (0.00 sec)

mysql> SAVEPOINT c;                     #记录保存点c
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM students;           #查看数据,就可以看到SID=8、9、10的行都删除了
+-----+--------------+------+--------+------+------+------+---------------------+
| SID | Name         | Age  | Gender | CID1 | CID2 | TID  | CreateTime          |
+-----+--------------+------+--------+------+------+------+---------------------+
|   1 | GuoJing      |   19 | M      |    2 |    7 |    3 | 2012-04-06 10:00:00 |
|   2 | YangGuo      |   17 | M      |    2 |    3 |    1 | 2012-04-06 10:00:00 |
|   3 | DingDian     |   25 | M      |    6 |    1 |    7 | 2012-04-06 10:00:00 |
|   4 | HuFei        |   31 | M      |    8 |   10 |    5 | 2012-04-06 10:00:00 |
|   5 | HuangRong    |   16 | F      |    5 |    9 |    9 | 2012-04-06 10:00:00 |
|   6 | YueLingshang |   18 | F      |    8 |    4 | NULL | 2012-04-06 10:00:00 |
|   7 | ZhangWuji    |   20 | M      |    1 |    7 | NULL | 2012-04-06 10:00:00 |
+-----+--------------+------+--------+------+------+------+---------------------+
7 rows in set (0.00 sec)

mysql> ROLLBACK TO b;  #回滚至保存点b
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM students;  #查看数据SID=8的那一行回来了
+-----+--------------+------+--------+------+------+------+---------------------+
| SID | Name         | Age  | Gender | CID1 | CID2 | TID  | CreateTime          |
+-----+--------------+------+--------+------+------+------+---------------------+
|   1 | GuoJing      |   19 | M      |    2 |    7 |    3 | 2012-04-06 10:00:00 |
|   2 | YangGuo      |   17 | M      |    2 |    3 |    1 | 2012-04-06 10:00:00 |
|   3 | DingDian     |   25 | M      |    6 |    1 |    7 | 2012-04-06 10:00:00 |
|   4 | HuFei        |   31 | M      |    8 |   10 |    5 | 2012-04-06 10:00:00 |
|   5 | HuangRong    |   16 | F      |    5 |    9 |    9 | 2012-04-06 10:00:00 |
|   6 | YueLingshang |   18 | F      |    8 |    4 | NULL | 2012-04-06 10:00:00 |
|   7 | ZhangWuji    |   20 | M      |    1 |    7 | NULL | 2012-04-06 10:00:00 |
|   8 | Xuzhu        |   26 | M      |    2 |    4 | NULL | 2012-04-06 10:00:00 |
+-----+--------------+------+--------+------+------+------+---------------------+


本文出自 “梅花香自苦寒来” 博客,请务必保留此出处http://wangjunkang.blog.51cto.com/8809812/1586074

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。