• MySql 技术内幕 (第8章 事务编程)


    8.1 事务概述

    事务应该满足ACID。(原子性,一致性,隔离性,持久性);

    • A(atomicity) 原子性:每条语句,或者一个事务,当做一个整体,要么成功,要么失败回滚。事务是一个不可分割的单位

    • C(consistency) 一致性:事务将数据库从一个状态转变为另外一种一致的状态,数据库的完整性约束不会被改变。 比如表中姓名不能重复,如果事务修改后回滚,表中数据姓名变得非唯一,则破坏了一致性;

    • I(isolation), 隔离性:别称并发控制,可串行化,锁。保证事务提交前其他事务看不见

    • D(durability),持久性:凡是提交了的事务,都应该持久化到磁盘上,即使数据库崩溃,也能通过日志来恢复。

     

    8.2 事务的分类

    1) 扁平事务

    实际生产环境中最频繁的一种事务,所有操作都处于同一层次,要么都执行,要么都回滚;

    - 优点:使用简单,广泛使用。

    - 缺点:不能提交事务的一部分,或分步骤提交。

     

    2) 带有保存点的扁平事务

    除了支持扁平事务外,允许在事务执行的过程中回滚到同一事务中的较早一个状态(保存点savepoint);

    当系统发生崩溃时,所有的保存点都将消失,因为其保存点是易失的,而非持久的。

     

    3) 链事务

    提交一个事务时,释放不需要的数据对象,将必要的处理上下文隐式的传给下一个要开始的事务。

    链式事务只能回滚仅限于当前事务,即只能恢复到最近一个保存点;

     

    4) 嵌套事务

    嵌套事务时一个层次结构框架,有一个顶层事务控制着各个层次的事务(子事务);

    mysql不是原生的;

     

    保存技术比嵌套查询更灵活;

    当使用保存技术,无论持有多少个保存点,所有被锁住的对象都可以被得到和访问;

    而嵌套查询中,不同的子事务在数据库对象上持有锁不同;

     

    5) 分布式事务

    通常是一个在分布式环境下运行的扁平事务;

    8.3 事务控制语句

    • START TRANSATION / BEGIN : 显式开启一个事务;

    • COMMIT 基本= COMMIT WORK

    • ROLLBACK 基本 = ROLLBACK WORK

    • SAVEPOINT xxx : SAVEPOINT允许在事务中创建一个保存点, 一个事务中可以有多个SAVEPOINT;

    • RELEASE SAVEPOINT xxx : 删除一个事务的保存点, 当没有一个保存点执行这个语句时,会抛出异常;

    • ROLLBACK TO [SAVEPOINT] xxx : 可以把事务回滚到标记点,

    例如:

    update语句1 ------> update语句2 ------> savepoint ------> DELETE语句1 ------> DELETE语句2;

    如果执行DELETE语句期间发生异常, 而且捕获到了这个异常,并发出ROLLBACK TO POINT 命令,事务就会回滚到指定的SAVEPOINT,撤销DELETE完成的所有工作, 而update语句完成的工作不受影响。

     

    • SET TRANSATION: InnoDB提供事务隔离级别有: (READ UNCOMMITTED / READ COMMITTED / REPEATABLE READ / SERIALIZABLE )

     

    在命令行下开启事务可以: BEGIN 。。。 END

    或者 START TRANSATION 。。。COMMIT

    但是在存储过程中,mysql数据库的分析器会自动的把BEGIN识别为 BEGIN...END,所以在存储过程中只能使用 START TRANSATION

     

    COMMIT 和 COMMIT WORK :

    语句基本上是一致的,都是用来提交事务。

    不同之处在于 COMMIT WORK 用来控制事务结束后的行为是CHAIN还是RELEASE的;

    如果是CHAIN则事务变成链事务;

    用户可以用completion_type来进行控制,

    默认该参数为0,没有任何操作,这种设置下 COMMIT和COMMIT WORK 完全等价;

    completion_type=1, COMMIT WORK 等同于 COMMIT AND CHAIN,表示马上自动开启一个相同隔离级别的事务;

    completion_type=2, COMMIT WORK 等同于 COMMIT AND RELEASE, 当事务提交后悔自动断开与服务器的联接 ;

     

    ROLLBACK和ROLLBACK WORK :

    与COMMIT 和 COMMIT WORK 的工作一样;

     

    ROLLBACK TO SAVEPOINT :

    可以回滚到一个不存在的保存点,会抛出异常;

    虽然有rollback 但并没有结束事务, 还需要显式地运行commit或rollback命令;

     

    8.4 隐式提交的SQL语句    

    8.7 不好的事务编程习惯

    8.7.1 在循环中提交

    不要在循环中提交。无论是显式提交还是隐式提交。

    每一次提交都要写一次redo日志;

    8.7.2 使用自动提交

    因为不同语言的API的自动提交设置是不一样的,容易出错。

    8.7.3 使用自动回滚

    最好是在程序中控制事务。

    8.8 长事务

    长事务: 执行时间较长的事务;

    长事务最好分为批量小事务。因为长事务如果失败,回滚的代价太大了。

     

    8.9 小结  

    • SET TRANSATION: InnoDB提供事务隔离级别有: (READ UNCOMMITTED / READ COMMITTED / REPEATABLE READ / SERIALIZABLE )

     

    在命令行下开启事务可以: BEGIN 。。。 END

    或者 START TRANSATION 。。。COMMIT

    但是在存储过程中,mysql数据库的分析器会自动的把BEGIN识别为 BEGIN...END,所以在存储过程中只能使用 START TRANSATION

     

    COMMIT 和 COMMIT WORK :

    语句基本上是一致的,都是用来提交事务。

    不同之处在于 COMMIT WORK 用来控制事务结束后的行为是CHAIN还是RELEASE的;

    如果是CHAIN则事务变成链事务;

    用户可以用completion_type来进行控制,

    默认该参数为0,没有任何操作,这种设置下 COMMIT和COMMIT WORK 完全等价;

    completion_type=1, COMMIT WORK 等同于 COMMIT AND CHAIN,表示马上自动开启一个相同隔离级别的事务;

    completion_type=2, COMMIT WORK 等同于 COMMIT AND RELEASE, 当事务提交后悔自动断开与服务器的联接 ;

     

    ROLLBACK和ROLLBACK WORK : 与COMMIT 和 COMMIT WORK 的工作一样;

     

    ROLLBACK TO SAVEPOINT :

    可以回滚到一个不存在的保存点,会抛出异常;

    虽然有rollback 但并没有结束事务, 还需要显式地运行commit或rollback命令;

    8.4 隐式提交的SQL语句    

    8.5 事务的隔离级别

    • READ UNCOMMITTED

    • READ COMMITTED

    • REPEATABLE READ

    • SERIALIZABLE

     

    InnoDB存储引擎默认支持的隔离级别是 REPEATABLE READ使用Next-Key Lock的锁算法,避免了幻读的产生。在这个级别下已经可以完全保证事务的安全性。达到SERIALIZABLE的隔离级别,但是性能比其好。

    隔离级别越低,事务请求的锁越少或保持锁的时间越短。

     

    SERIALIZABLE :

    InnoDB会对每一个select 语句后自动加上LOCK IN SHARE MODE,即 给每个读取操作加一个共享锁, 在这个事务隔离级别下,读占用锁了;

    SERIALIZABLE主要用于InnoDB的分布式事务;

     

    READ COMMITTED :

    除了唯一性约束检查及外键约束的检查需要Gap lock,InnoDB存储引擎不会使用Gap Lock锁算法。(注意,mysql5.1以前,这个隔离级别只能工作在Replication(复制)的二进制日志为Row格式下。mysql5.1后不会了,也可以工作在STATEMENT格式下。) 最好建议是选择Row格式的二进制日志。因为记录的是行的变更,而不是SQL语句。避免出现主从不同步的现象 ;

     

    事务的并发问题:

    • 脏读 (读后数据回滚):事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

    • 不可重复读 (修改导致重复读数据不一致) :事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

    • 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

    • 小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。

    解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

     

     

    小结:

    1、SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异

    2、mysql中默认事务隔离级别是可重复读时并不会锁住读取到的行

    3、事务隔离级别为读提交时,写数据只会锁住相应的行

    4、事务隔离级别为可重复读时,

        如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁、行锁、下一键锁的问题,从而锁住一些行;

        如果没有索引,更新数据时会锁住整张表。

    5、事务隔离级别为串行化时,读写数据都会锁住整张表

    6、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,鱼和熊掌不可兼得。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

     

    8.6 分布式事务编程

    允许多个独立的事务资源参与到一个全局的事务中。全局事务中的事务要么全都成功,要么都回滚。在使用分布式事务时,InnoDB的隔离级别必须是SERIALIZABLE的。 InnoDB支持XA事务,并通过XA事务来支持分布式事务。异构分布式数据库可以通过XA事务实现分布式事务。

     

    XA事务:

    • 一个或多个资源管理器(提供访问事务资源的方法,一个数据库就是一个资源管理器)

    • 一个事务管理器(协调参与全局事务中的各个事务)

    • 一个应用程序(定义事务的边界,指定全局事务中的操作)

     

    分布式事务使用两段提交的方式:

    第一阶段,所有参与全局事务的节点都开始准备(prepare),告诉TM, 它们准备好提交了;

    第二阶段,TM告诉RM's 执行ROLLBACK或者COMMIT;

    如果任何一个节点显示不能提交,则所有节点都被告知需要回滚;

     

    Mysql内部也是通过XA事务来协调两张表的操作,实现原子性的;

     

    8.7 不好的事务编程习惯

    8.7.1 在循环中提交

    不要在循环中提交。无论是显式提交还是隐式提交。

    每一次提交都要写一次redo日志;

    8.7.2 使用自动提交

    因为不同语言的API的自动提交设置是不一样的,容易出错。

    8.7.3 使用自动回滚

    最好是在程序中控制事务。

    8.8 长事务

    长事务: 执行时间较长的事务;

    长事务最好分为批量小事务。因为长事务如果失败,回滚的代价太大了。

     

    8.9 小结  

     

     

  • 相关阅读:
    获取项目中.txt 文件的内容
    jdbc 连接各种数据库
    修改Eclipse中项目在Apache Tomcat中的部署路径
    java学习之继承之子父类中变量的特点
    java学习之继承、多态
    java学习之单例模式(饿汉式与懒汉式)
    java学习之对象初始化过程
    java学习之静态块、显示初始化块、构造函数、this在构造函数中的调用,区别联系与调用顺序
    java学习之数组的两种常见错误
    java学习之堆与栈的区别
  • 原文地址:https://www.cnblogs.com/coloz/p/13589992.html
Copyright © 2020-2023  润新知