zoukankan      html  css  js  c++  java
  • MySQL事务2013530

    资料:1.《MySQL技术内幕》SQL编程 2.《MySQL技术内幕》第四版

    事务(transcation)是数据库区别文件系统的重要特征之一。事务就是将作为一个不可分割的逻辑单元而被执行的SQL语句(DML语句),该组语句要么全部成功,要么全部失败。

    从理论上说事务应该是同时满足ACID特性。

    A(atomicity),原子性。就死构成事务的所有SQL语句都是一个逻辑单元,不可分割,不能只执行它们中的一部分。

    C(consistency),一致性。即你在事务开始前和事务执行完之后,数据库的完整性没有被破坏,必须是稳定的。换句话说就是不应该经过执行事务之后吧你的数据库搞的一团乱。

    I (isolation),隔离性。每个事务对其他的事务都是不可见的,不应该互相影响。

    D(dirable),持久性。事务一旦提交,其结果时永远的被记录到数据库系统中。

    MySQL是否支持事务安全是由数据引擎决定的,比如或MySQL的Innodb存储引擎和Falcon存储引擎是支持事务,而MyISAM存储引擎不支持事务安全性。

    就以上的举个例子:A去银行转账,将100块钱转给B。银行系统需要作出的就是从A的账户上减去100,在B的账户上加上100。        

             update transcation1 set menory = (menory-100) where name='A';
             update transcation1 set menory = (menory+100) where name='B';
    

      但是如果在万一银行在执行的过程中发生了意外,第一条语句执行完了。整个操作将不完整。A的账户了可以少了100,但是B的账户没有增加。如果没有事务,那就必须去手动去修改为原来的状态。

          就是事务的原子性,这两条语句必须是做为一个单元,要么全部失败,要么全部成功,数据也能和原来保持一致了。

          在MySQL命令行下的默认设置下,事务都是自动提交的,即当语句执行后就马上执行commit操作。用户对事务的控制语句主要有这些

          1.start transction或者begin:显示的开启一个事务,即不commit之前将不会自动提交。

            commit或者rollback:提交或者回滚。

            这一组一般都是一起的,所以再这里一起讨论。

        create table t(a_id int unsigned auto_increment,primary key(a_id),name varchar(10) not null,menory decimal(10,2));这是上面的例子创建的表
    

       首先插入两条数据

     insert into t values (null,'A',100.00),(null,'B',100.00);
    select * from t;
    a_id  name menory
    1 A 100.00
    2 B 100.00

      

      如果再银行需要再增加一个账户

    mysql> start transaction;
    mysql> insert into t values(null,'C',1.00);
    

      此时如果你启动另外一个mysql程序的实力后查询这个表格在提交之前是无法查询到的。结果还是原来的两条数据。当在commit之后另一个mysql窗口中才能看到。

         如果在插入D客户之后你发现这个D客户的金额数出错了,不要commit,直接rollback。之后再commit 也不会插入Dz这个客户。

    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(null,'D',2.
    Query OK, 1 row affected (0.00 sec)
    
    mysql> rollback;
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> commit;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select* from t;
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    1 | A    | 100.00 |
    |    2 | B    | 100.00 |
    |    3 | C    |   1.00 |
    +------+------+--------+
    3 rows in set (0.00 sec)
    

     显示的开始一个事务使用begin 和start transaction是等价的。

       还有一种开始一个事务的方法就是set autocommit来开始事务,例

    重新将表格清空,方便看清楚
    mysql> truncate table t;
    Query OK, 0 rows affected (0.07 sec)
    
    mysql> select * from t;
    Empty set (0.00 sec)
    
    mysql> set autocommit=0;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(null,'A',200.00
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into t values(null,'B',200.00
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from t;  插入两行后查询表有这两行
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    1 | A    | 200.00 |
    |    2 | B    | 200.00 |
    +------+------+--------+
    2 rows in set (0.00 sec)
    
    mysql> rollback;
    Query OK, 0 rows affected (0.07 sec)
    
    mysql> select * from t;         执行rollback后查询表为空
    Empty set (0.00 sec)
    
    mysql> insert into t values(null,'A',200.00
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into t values(null,'B',200.00
    Query OK, 1 row affected (0.00 sec)
    
    mysql> commit;
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> select * from t;
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    3 | A    | 200.00 |
    |    4 | B    | 200.00 |
    +------+------+--------+
    2 rows in set (0.00 sec)
    
    mysql> insert into t values(null,'C',200.00           commit前两条之后插入第三条
    Query OK, 1 row affected (0.00 sec) 
    
    mysql> rollback;                                      
    Query OK, 0 rows affected (0.11 sec)
    
    mysql> select * from t;                  rollback后还是没有插入C到t表,说明还是没有自动提交,需要你去手动的设置autocommit=1;不向start transaction那样能回到事务之前的状态
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    3 | A    | 200.00 |
    |    4 | B    | 200.00 |
    +------+------+--------+
    2 rows in set (0.00 sec)
    

      2.savepoint identifier:savepoint允许在事务中创建一个保存点,一个事务中可以有多个savepoint;

          例:还是使用之前的表,清空之前的表,其实在start transaction是隐式的创建了一个savepoint.

    mysql> select *from t;
    Empty set (0.00 sec)
    
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(null,'A',200.00);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into t values(null,'B',200.00);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> savepoint mypoint_1;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(null,'C',200.00);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> rollback to savepoint mypoint_1;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(null,'D',200.00);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> commit;
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> select * from t;   结果是C没有被插入
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    1 | A    | 200.00 |
    |    2 | B    | 200.00 |
    |    4 | D    | 200.00 |
    +------+------+--------+
    3 rows in set (0.00 sec)

      3.release savepoint identifier:删除一个事务的保存点,当没有一个保存点执行这句话,会抛出一个异常。这里就不做例子了。

         此外commit和commit work语句基本上是一致的,都用来提交事务的。不同之处在于commit work用来控制事务结束后的行为时chain还是release。

         如果是chain那么事务就成了链式事务了。可以使用completion_type来进行控制,默认该参数为0,

         当completion_type的参数为1时,commit work就等同于commit and chain,表示马上自动开启一个相同的隔离界别的事务。

         例

    mysql> set @@completion_type=1;                       将completion_type设置为1,表示chain事务了。
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> begin
        -> ;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(null,'A',100.22);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into t values(null,'B',100.22);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> commit work;                                  插入两条记录后commit
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> insert into t values(null,'C',100.22);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> insert into t values(2,'D',100.22);       
    ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
    mysql> rollback;                                    这里rollback,后查询出来的只有A和B,说明C被回滚了,这里autocommit也是1说明是commit work时候有开始了一个隔离性的事务。
    Query OK, 0 rows affected (0.08 sec)
    
    mysql> select * from t;
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    1 | A    | 100.22 |
    |    2 | B    | 100.22 |
    +------+------+--------+
    2 rows in set (0.00 sec)
    

      当chompletion_type=2时,commit work等同于commit and release.当事务提交后会自动断开与服务器的连接。

         例:

    mysql> set @@completion_type=2;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> begin;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into t values(2,'D',100.22);
    ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
    mysql> insert into t values(null,'D',100.22);
    Query OK, 1 row affected (0.00 sec)
    
    mysql> commit work;
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> select version();
    ERROR 2006 (HY000): MySQL server has gone away
    No connection. Trying to reconnect...
    Connection id:    5
    Current database: sampdb
    

      还有需要注意的在rollback to point后还需要显示的调用commit或者rollback命令。

          

         事务支持四种不同的隔离级别。

         这里先说说隔离级别,就是对事务的隔离性的控制,不然它会发生的问题:

          1.脏读:指某个事务为提交时,就可以被其他事务看到。其的事务认为数据行已经被修改了,但对数据行作出的修改那个事务还有可能会回滚,这肯定会导致数据表混乱。

          2.不可重复读取:指一个事务使用同一个select语句读取数据表的数据,但是另一个事务在两个select中间对数据行进行修改,这样两次读取的数据就不一样。

          3.幻影数据行:这不可重复读取时同一个原来,在第二个select前,另一个事务插入了数据行。

         再说说事务的这四个隔离级别(对于Innodb存引擎):

           READ UNCOMMITED:允许某个事务看到其他事务未提交的数据行动。

           READ COMMITED:只允许某个事务看到其他事务已经提交的数据行改动。

           REPEATABLE READ:即使有其他的事务在同时插入或数据行,这个事务所看到的结果也是一样的。在MySQL的Innodb中使用了Next-key lock锁算法(这个我不知道),因此避免了幻影数据行。                           

           SERIALIZABLE:在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新或插入记录,使事务串行执行,是四个隔离级别中限制最大的隔离级别,有可能会导致死锁或超时。并发度最低,慎用

          刚刚上面的例子,一个事务在为提交时,另一个mysql程序是看不到提交的数据的。上次是这样,因为InnoDB默认的隔离级别是repeatable read).

           这是mysql窗口1:此时没有进行commit

    mysql> set global transaction isolation level read uncommitted;
    Query OK, 0 rows affected (0.00 sec)

    mysql> use sampdb
    Database changed
    mysql> start transaction;

    Query OK, 0 rows affected (0.00 sec)

    mysql> insert into t values(null,'C',100);
    Query OK, 1 row affected (0.00 sec)

         窗口2的内容

    mysql> select * from t;
    +------+------+--------+
    | a_id | name | menory |
    +------+------+--------+
    |    1 | A    | 100.11 |
    |    2 | B    | 100.11 |
    |    3 | C    | 100.00 |
    +------+------+--------+
    3 rows in set (0.00 sec)
    

      这里窗口2的能看到窗口1插入的数据,但是还有commit.

          

            

         

  • 相关阅读:
    Atitit orm 之道 艾龙著 1. 一、ORM的由来 1 2. ORM的组成:      2 3.  常见的ORM框架:      3 4. 、ORM与数据持久化的关系 3 5. Atitit
    Atitit 移动互联网 产业维度 1. 移动互联网带来的模式变革  1 2. 从视窗到“苹果与机器人”,软件发展模式的颠覆  2 3. 第3章 从X86到ARM,蚂蚁绊倒了大象  2 4. 第5
    Atitit 装备工具分类 attilax总结 艾龙著 工具链体系 武器与软件行业工具也是很近似的的。 1. 分类思维 1 1.1. 总分类:冷、热 1 1.2. 轻、重、大规模杀伤性 1
    Atitit 区块链之道 attilax著 艾龙著 1. 金融=制度+技术+信息 1 2. 第一章可信的协议 1 3. 第二章引导未来:区块链经济七大设计原则 1 4. 第五章 新商业
    Atitit 几大研发体系对比 StageGate体系 PACE与IPD体系 敏捷开发体系 CMMI体系 艾龙 著 1. 3. 1.5:业界领先的研发管理体系简介 2 1 2. 《产品及生命周期
    Atitit 传感器之道 1. 视觉传感器 摄像头 1 1.1. 一、光线传感器: 1 1.2. 二、距离传感器: 1 1.3.    第一种是震动传感器。 4 1.4.   第二种是声响传感
    Atitit 架构之道 之 可读性可维护性架构之道 提升效率架构之道 attilax著 艾龙 著 1.1. Hybrid架构 1 1.2. 分层架构是使用最多的架构模式 Layers模式 也称Tie
    Atitit cko之道首席知识官之道 attilax著 艾龙著 1. 2 2. 第 1 章 知识管理到底是什么,有什么用/1 2 3. 1.1 知识管理全景/1 1.2 波士顿矩阵/3 1.2.
    Atitit 提升效率 降低技术难度与提升技术矛盾的解决方案 1. 问题 2 1.1. 高手喜欢技术挑战怎么办,但会提升技术难度 导致新手不会用怎么办 2 2. 解决方案 2 2.1. 通过开会统
    Atitit 依赖管理之道 1. 概念 依赖管理,是指在什么地方以什么形式引入外部代码。 1 1.1.1. 理解模块化和依赖管理: 1 1.2. 依赖管理,有三个层面。 单一职责原则,协议对象引用,
  • 原文地址:https://www.cnblogs.com/evencao/p/3108706.html
Copyright © 2011-2022 走看看