• 分布式事务01课前知识


    问题

    1. 事务的几个特点

    2. 数据库事务有哪些隔离级别

    3. MySQL的默认隔离级别

    考点

    mysql开发的三个基本面:存储引擎(了解)、索引(重要)、事务(了解原生及spring事务)

    回答

    事务特点

    ACID

    A原子性: 事务里的所有sql, 要么都成功, 要么都不成功

    C一致性(不是很懂, 抄来的): 事务开始/结束不影响数据库的一致性

    1. 数据库机制层面
      数据符合设置的约束条件, 由唯一索引/外键/check约束/触发器保证

    2. 业务层面
      由研发人员保证, 但一般会转为数据库机制层面保证

    I隔离性: 设计到事务的隔离机制, 根据机制的选择不同, 各个事务之间的结果也不同

    D持久性: 落库, 只要提交就一定成功, 即使是断电也会通过数据库的机制保证成功(redolog)

    I隔离性相关的隔离级别

    四个隔离级别

    读未提交
    一个事务还没提交, 另一个事务就读到了结果...

    读已提交(不可重复读)
    (Oracle默认级别)
    能读取到已经提交的事务结果(针对单条数据)
    举例:
    事务A, 先查一次, 结果为1
    事务B, 在事务A查询之后, 改成结果2
    事务A, 再查一次, 结果为2

    可重复读
    一个事务中的查询结果是不变的(针对单条数据)
    (mysql默认隔离级别, mysql里该级别可以解决幻读)
    举例:
    事务A, 开始查的是1, 即使中途有其他事务改了结果, 事务A查出来还是1

    串行化
    事务A执行完毕, 才能执行事务B
    主要是为了防止幻读:
    幻读针对插入, 比如事务A已经将所有的行的数据修改为2了, 但是另一个事务B插入了一条数据为1, 那么事务A此时再查询就会有未修改的一条数据

    mysql默认隔离级别是如何解决幻读

    通过MVCC机制(多版本并发控制,multi-version concurrency control), 类似于快照。
    简单来说就是多两个隐藏列: 该行创建的事务id, 该行删除时的事务id
    查询默认带条件: 创建事务id <= 当前事务id && 当前事务id < 删除事务id

    举例:

    id name 创建事务id 删除事务id
    1 张三 120
    2 李四 119

    事务A, 事务id: 121
    事务B, 事务id: 122, 把id2的李四改成了小李四, 此时插入一条数据; 再把id=1的数据删除

    id name 创建事务id 删除事务id
    1 张三 120 122
    2 李四 119
    2 小李四 122

    事务A, 事务id: 121
    查询id=1, 可以查到(当前事务id 121 < 删除事务id 122);
    查询id=2, 还是李四(创建事务id 120 <= 当前事务id 121 && 当前事务id 121< 删除事务id 122)

    事务B, 事务id: 122
    查询id=1, 查不到(当前事务id 122 不小于 删除事务id 122);
    查询id=2, 查询为小李四(创建事务id 122 <= 当前事务id 122)

    spring的事务机制

    记得把日志的级别开成 debug

    测试三个状态
    伪代码
    都成功:

    serviceA save () {
       insert();
       
       serviceB.delete();
    }
    

    调用方在被调用方执行完毕后报错:

    serviceA save () {
       insert();
       
       serviceB.delete();
       throws Exception;
    }
    

    被调方报错;

    serviceA save () {
       insert();
       serviceB.delete( throw Exception);
    }
    

    REQUIRED, 被调用方(ServiceB)开启事务, 如果有调用方ServiceA有事务则加入调用方的事务, 两者合成一个事务, 任何一方出错, 全部回滚; 如果调用方ServiceA没有事务, 则被调用方ServiceB创建单独的事务, ServiceB出错的回滚自己, 和ServiceA无关, 即只有B的事务

    1. ServiceA, REQUIRED
    2. ServiceB, REQUIRED

    合并到一个A的事务中

    NOT_SUPPORTED, Spring不为当前方法开启事务,相当于没有事务, 调用方A有事务, 会无法执行B为NOT_SUPPORTED, 会报错

    1. ServiceA, NOT_SUPPORTED
    2. ServiceB, REQUIRED

    B会开事务, A不会, 所以只会回滚B

    REQUIRES_NEW, 不管是否存在事务,都创建一个新的事务,原来的方法挂起,新的方法执行完毕后,继续执行老的事务

    1. A: REQUIRED,
    2. B: REQUIRES_NEW,
      B事务报错, A事务catch了, 那么只会B事务回滚, A事务照常

    MANDATORY, 必须要在一个事务中, 不然就报错

    1. A: 无事务,
    2. B: MANDATORY,

    报错:
    No existing transaction found for transaction marked with propagation 'mandatory'

    NEVER, 必须在无事务环境下执行, 不然就报错

    1. A: REQUIRED,
    2. B: NEVER,

    报错:
    Existing transaction found for transaction marked with propagation 'never'

    SUPPORTS, 看调用方是否存在事务, 有加入事务, 没有就不加

    1. A: REQUIRED,
    2. B: SUPPORTS,

    会加入A事务, 如果A没有事务, 则都没有事务

    NESTED, 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作

    1. A: REQUIRED,
    2. B: NESTED,

    还要看mysql的环境,
    The MySQL server is running with the --transaction-write-set-extraction!=OFF option so it cannot execute this statement
    会报错, NESTED会不成功

    据说执行的效果,save方法创建一个事务,则再调用delete方法时,直接在该事务的基础上创建一个嵌套事务,本质上还是同一个事务,做一次提交;
    save方法不创建事务,则调用delete方法时,直接创建一个新的事务,单独提交

    https://blog.csdn.net/dufufd/article/details/51479860

    https://blog.csdn.net/qq_26323323/article/details/81908955

  • 相关阅读:
    Java单例模式
    svn 清理失败 (clean up 失败) 的解决方法
    linux chrome 安装过程记录
    docker
    linux-cat-grep
    linux-批量结束进程
    linux-压缩与解压缩(gz,zip,tar,jar,war)
    git-服务器地址切换
    linux-tomcat连接数查询
    git-无法add文件的问题
  • 原文地址:https://www.cnblogs.com/richardwlee/p/15774517.html
Copyright © 2020-2023  润新知