大数据WEB阶段(十八)数据库事务

数据库事务

一、概述

  1. 事务的概念
    1. 事务是指逻辑上的一组操作 , 组成这组操作的各个单元 , 要么全部成功 , 要么全部失败 。 如:银行转账。。
      1. 转账核心操作其实就是两条sql ,两条都执行成功才算成功 , 一条失败则转账失败 。 决不允许一部分成功一部分失败的情况
    2. 关系型数据库可以事务操作保证事务的特性。

二、 管理事务

  1. 数据库默认就有事务 , mysql中默认一条语句独占一个事务
  2. 也可以通过手动控制事务:
    1. sql控制事务
      1. start transaction; #开启一个事务, 这条语句后面的所有sql都将处在同一个事务当中 。这些sql都不会立即起作用 — 没有改变真正改变数据库中数据的操作 。
      2. commit;# 提交事务 , 这个事务中的所有sql对数据库的影响立即发生 , 真正改变数据库的数据 。 未提交之前 , 在表面上发生改变事务内部的数据 , 但是实际上并没有对数据库的数据产生影响。
      3. roilback;# 回滚事务,撤销这个事务中的所有的操作可能对数据库 产生的影响。
    2. JDBC中控制事务
      1. conn.setAutoCommit(false);//关闭jdbc自动提交 ,开启jdbc的事务功能 , 接下来在这个连接执行的所有sql都将处在同一个事务中
      2. conn.commit() //提交事务 , 将这个连接上执行的事务提交 , 对数据库产生影响
      3. conn.roliback() //回滚事务 , 取消这个连接上的执行的事务
      4. SavePoint sp = conn.setSavePonit(); //设置回滚点 , 相当于游戏中的存档
      5. conn.roliback(sp);//回滚到回滚点 , 注意:回滚到回滚点时 , 回滚点之前的代码仍然是未提交的状态 , 如果希望对数据库产生影响仍然需要进行提交操作

三、事务的四大特性 — ACID

  1. 原子性 : 事务中的一组操作是不可分割的一个整体 , 要么一起成功 , 要么一起失败
  2. 一致性 : 事务前后无论事务是否成功 , 数据库都应该保持一个完整性的状态
    1. 数据库中数据的完整性 : 数据库中数据是业务完整的(符合业务逻辑)且是约束完整的(符合数据库中所定义的所有约束)。
  3. 隔离性 : 多个事务之间应该互相隔离 , 互不影响 。
  4. 持久性 : 一个事务一旦完成 , 对数据库的影响是永久性的 , 无论发生什么情况 , 这种影响都不会被取消 。

四、隔离性的问题:

  1. 方案一 : 加锁 – 保证同一时间内只能有一个操作数据 – 完美的保证隔离性 – 但是这样一来数据库就相当于单线程的状态下 , 同一时间只能有一个人操作数据库 , 效率牺牲过大 。
  2. 方案二 : 现实生活中 , 并不是所有场景下都需要 那么严格的隔离 , 在不同的业务场景下 , 对隔离的要求是不同的 , 数据库的设计者并没有将隔离性写死 , 而是提供了不同的选项 , 数据库使用者根据自身需求选择对应的选项 , 选择相应的隔离能力和数据库的性能 。 通过这些选项 , 数据库 的使用者可以在数据库的性能和隔离性之间做一个权衡

五、四大隔离级别

  1. Read uncommitted – 读未提交
    1. 数据库不保证任何的事务特性 , 可能出现脏读、不可重复读、幻读的问题。隔离性最低 ,但是性能最高
    2. 脏读: 一个事务读取到了另一个事务未提交的数据。
  2. Read committed – 读已提交
    1. 保证部分的隔离 , 可以防止脏读问题 ,但是具有不可重复读 和 幻读的问题 。
    2. 不可重复读:一个事务读取到另一个事务已经提交的数据
  3. Repeatable read – 可重复读
    1. 保证了部分的隔离 , 可以防止脏读、不可重复读的问题 , 但是具有幻读的问题
    2. 幻读: 一个事务读取全表数据时, 读取到另一个事务向表中新增或删除操作提交后的数据。
      1. 幻读问题有可能出现 , 有可能不出现 , 概率很低。 是由于快照造成的
  4. Serializable – 可序列化
    1. 保证了完全隔离 , 可以防止脏读 , 不可重复读 , 幻读的问题 , 本质上是 通过锁实现的 。
  5. 从安全性来说:serializable >Repeatale read > Read committed > Read uncommittes
  6. 从效率来说:serializable

六、隔离级别的操作

  1. 查看数据库隔离级别:

    select @@tx_isolation;
    
  2. 设置数据库隔离级别

    set [session/globle] transaction isolation level ****;
    session表示只设置当前 客户端的隔离级别 , 立即生效 ; globle表示设置数据库的默认隔离级别 , 但是不会立即生效 , 需要从启客户端
    

七、数据库中的锁机制

  1. 数据库中是有锁的 , 但是锁如果设计不好对效率的影响非常大 , 所以数据库的设计者对锁做了详细的设计
    1. 两个查询 — 没有必要排斥
    2. 两个修改 — 必须要排斥
    3. 一个查询 , 一个修改 — 根据具体场景加锁 , serializable级别 下需要排斥 , 其他隔离级别下不需要
  2. 共享锁
    1. 共享锁和共享锁可以共存 , 共享锁和排它锁不能共存
    2. 在非serializable级别中查询不加任何锁 , 在serializable级别中查询加共享锁
  3. 排它锁
    1. 排它锁和任何锁不能共存
    2. 在任意隔离级别下增删改都加排它锁
  4. 案例:

    非serializable级别下操作非serializable级别下操作结果
    查询 不加任何锁查询 不加任何锁共存
    增删改 排它锁查询 不加任何锁共存
    增删改 排它锁增删改 排它锁排他
    serializable非serializable结果
    查询 共享锁查询 不加任何锁共存
    增删改 排它锁查询 不加任何锁共存
    增删改 排它锁增删改 排它锁排他
    serializableserializable结果
    查询 共享锁查询 共享锁共存
    查询 共享锁增删改 排它锁排他
    增删改 排他锁增删改 排它锁排他
  5. 死锁

    1. 当两边都是serializable隔离级别时, 两边都先进行查询,这时两边都是共享锁, 再尝试修改 企图将共享锁升级为排它锁, 则造成了死锁的现象, 互相等待对方释放共享锁 , 都无法执行 , 造成死锁。
    2. 两种解决办法:
      1. 提前避免死锁的发生
      2. mysql没有避免死锁 , 尝试检测死锁 ,发现死锁的时候 ,错误推出一方 , 执行另一方的方式解决了死锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值