zoukankan      html  css  js  c++  java
  • 数据库系统原理

    数据库系统原理

    事务

    四大特性—ACID

    • 原子性(Atomicity)
      • 事务不可再分,要么执行成功、要么失败回滚。回滚操作采用混滚日志(Undo Log)的方式实现。
    • 一致性(Consistency)
      • 事务执行前后数据库保持一致性状态,所有事务对同一个数据的读取结果都是相同的。
    • 隔离性(Isolation)
      • 某个事务所作的修改在提交以前对其他事务不可见
    • 持久性(Durability)
      • 事务一旦提交,所作的修改将永远保存到数据库中。即使系统发生崩溃,也可以通过重做日志(Redo Log)的方式恢复。

    ACID的关系

    • 事务的持久化是为了应对系统崩溃造成的数据丢失
    • 只有保证了事务的一致性,才能保证执行结果的正确性
    • 非并发状态下,事务间天然保证隔离性,因此只需要保证事务的原子性即可保证一致性
    • 并发状态下,需要严格保证事务的原子性、隔离性

    并发一致性问题—并发状态下如何保证隔离性

    并发状态下会出现的一致性问题

    • 丢失修改—并发修改
      • 事务A所作的修改被并发事务B的修改覆盖
    • 脏读—修改时读
      • 事务A读到了并发事务B未提交的修改
    • 不可重复读—读时修改
      • 事务A读取数据期间并发事务B对数据进行了修改,导致事务A读取前后数据不同
    • 幻读
      • 事务A读取某个范围的数据期间并发事务B插入的新数据,导致事务A前后读取的该范围数据不同

    事务加锁/封锁

    • 解决问题 前三种问题(丢失修改、脏读、不可重复读)是由于并发事务对同一数据进行修改导致的,可以通过对事务加锁的方式解决

    • 封锁粒度—行锁、表锁(MySQL服务器只支持表锁,只有存储引擎入InnoDB等实现了表锁)

    • 封锁原则—满足要求的情况下锁定尽可能少的数据,但更小的锁粒度也会带来更大的锁开销

    • 封锁类型—读写锁、意向锁

      • 读写锁——写锁/互斥锁/X锁、读锁/共享锁/S锁
        • 加了S锁则只能再加S锁,且只能读取数据而不能修改
        • 加了X锁则不能再加任何所,只有持有锁的事务能够进行读取、修改
      • 意向锁——再X/S锁的基础上增加了意向表锁IX/IS, 表明想要对表加X/S锁(并不是真正加锁)
        • 一个事务在获得某个数据行对象的 S 锁之前,必须先获得表的 IS 锁或者更强的锁
        • 一个事务在获得某个数据行对象的 X 锁之前,必须先获得表的 IX 锁
        • 事务 T 想要对表 A 加 X 锁,只需要先检测是否有其它事务对表 A 加了 X/IX/S/IS 锁
        • 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁
        • 这里兼容关系针对的是表级锁,而表级的 IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T1 想要对数据行 R1 加 X 锁,事务 T2 想要对同一个表的数据行 R2 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
    • 封锁协议

      • 三级封锁协议

        • 一级封锁(解决丢失修改)
          事务修改时加X锁,直到事务结束释放

        • 二级封锁(解决脏读)
          一级封锁基础上(修改时加X锁),读取时必须加S锁,直到事务结束立即释放

        • 三级封锁(解决不可重复读)
          二级封锁基础上,读取时必须加S锁

      • 两段锁协议

        • 加锁、释放分两个阶段进行(先全部加锁、再全部释放)
        • 串行化调度 并发事务执行结果与串行执行结果一致

    隔离等级

    • 事务的隔离级别
      • 读未提交(READ UNCOMMITTED)
        事务中的修改,即使没有提交,对其它事务也是可见的。

      • 读提交(READ COMMITTED)
        一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。

      • 可重复读(REPEATABLE READ)
        保证在同一个事务中多次读取同一数据的结果是一样的。

      • 可串行化(SERIALIZABLE)
        强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。
        该隔离级别需要加锁实现,因为要使用加锁机制保证同一时间只有一个事务执行,也就是保证事务串行执行。

    多版本并发控制MVCC——实现隔离等级(读提交、可重复读)的方式

    • 写操作更新最新版本的快照,读操作读旧版本快照,一个事务只能读取已提交的快照
    • MVCC 中事务的修改操作(DELETE、INSERT、UPDATE)会为数据行新增一个版本快照
    • 版本号:
      • 系统版本号SYS_ID: 是一个递增的数字,每开始一个新的事务,系统版本号就会自动递增
      • 事务版本号TRX_ID: 事务开始时的系统版本号
    • Undo日志:
      • 每一行记录拥有一系列快照
      • 快照中包含对该行数据的操作、版本号(对该行数据进行操作的事务版本号)、该行记录的关键字
      • 同一行记录的快照使用回滚指针(ROLL_PTR)串联, 从新的版本号(大)指向旧版本号(小)
    • ReadView:
      • 记录了当前系统内所有未提交事务的列表
    • 读快照的规则:
      • 查找要读取记录的最新事务号TRX_ID
      • 与ReadView中最小事务号TRX_ID_MIN和最大事务号TRX_ID_MAX比较,若TRX_ID < TRX_ID_MIN则可以读取
      • 若TRX_ID > TRX_ID_MAX则无法读取
      • 若TRX_ID > TRX_ID_MIN 且 TRX_ID < TRX_ID_MIN则需要参考隔离级别
        • 读提交: 如果 TRX_ID 在 TRX_IDs 列表中,表示该数据行快照对应的事务还未提交,则该快照不可使用。否则表示已经提交,可以使用。
        • 可重复读:都不可以使用。因为如果可以使用的话,那么其它事务也可以读到这个数据行快照并进行修改,那么当前事务再去读这个数据行得到的值就会发生改变,也就是出现了不可重复读问题。
    • 快照读和当前读
      • 读(Select)快照
      • 写操作永远使用加锁的方式获取最新数据

    Next-Key Locks

    • RecordLocks: 锁定一个记录上的索引,而不是记录本身。如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks 依然可以使用。
    • GapLocks: 锁定索引之间的间隙,但是不包含索引本身
    • Next-KeyLocks: 它是 Record Locks 和 Gap Locks 的结合,不仅锁定一个记录上的索引,也锁定索引之间的间隙, 它锁定一个前开后闭区间

    关系数据库设计理论

    ER图

  • 相关阅读:
    Tomcat 启动很慢?
    CentOS 下 安装 JDK8
    CentOS 下 安装 nginx
    SpringBoot 之 打war包
    Spring MVC处理异常有3种方法
    springboot 之 使用jetty web容器
    IDEA 中,编译后不拷贝 mybatis 配置的 mapper 的 xml 文件
    js 鼠标点击页面出现文字
    PHP 获取天气
    js 必须为字母或下划线, 一旦创建不能修改
  • 原文地址:https://www.cnblogs.com/CodeSPA/p/13552683.html
Copyright © 2011-2022 走看看