栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【数据库】数据库原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【数据库】数据库原理

1、事务

概念:事务是满足ACID特性的一组操作

  • 原子性(Atomic):一组操作要么都执行,要么都不执行
    执行失败的事务,通过回滚将已执行的操作进行撤销。回滚通过回滚日志(Undo Log)来实现,它记录着事务执行所作的操作,反向执行就可以恢复事务前的状态
  • 一致性(Consistency):数据库在事务执行前或后都保持一致性状态
    就是说在事务执行之前或执行之后,所有其他事务对同一个数据的读取结果是相同的,不存在你读是一个值,另一个操作读又是另一个值的情况
  • 隔离性(Isolation):一个事务所作的修改,在提交之前,对其他事务是不可见的
  • 持久性(Durability):事务一旦提交,它所做的修改将永久地保存在数据库中,即使系统崩溃也不能丢失
    系统发生崩溃可以用重做日志(Redo Log)进行恢复,从而实现持久性。与回滚日志记录数据的逻辑修改不同,重做日志记录的是数据页的物理修改

undo log 和 redo log

  • undo log记录的是逻辑修改,并不是真实的对数据库的修改,当事务回滚时,将逻辑恢复为原来的样子
    用途:事务的回滚,MVCC
    分类:
    insert undo log 是插入数据产生的undo log,只对本条事务可见,所以事务提交后可以删除
    update undo log是删除或修改时产生的undo log,可能提供MVCC,所以事务提交后不可删除
  • redo log主要应对系统崩溃的情况,记录的是数据页的物理变化,当数据库崩溃的时候,将数据库恢复为原来的样子
    组成:redo log buffer 和 redo log file,分别存在内存和磁盘中
    记录时机:内存中数据——内存中redo——磁盘redo——磁盘数据
2、并发一致性问题

并发环境下,很难保证事务之间的隔离性,因此会发生很多一致性问题

  • 丢失修改:一个事务的更新操作被另一个事务的更新操作覆盖了
  • 脏读:一个事务读到了另一个事务未提交的数据,如果那个事务后面回滚了,读到的就是一个无效的脏数据
  • 不可重复读:同一个事务内,前后读同一个数据,读到的值不一致
  • 幻读:一个事务内两次读一个范围的数据,之间有另一个事务往这个范围内插入了新数据,导致这两次都读的结果不一样,本质上也属于不可重复读

通过并发控制可以解决并发一致性问题,一个途径是加锁,但是如果让开发人员控制加锁太复杂了,数据库管理系统提供了事务间的隔离级别,来简化这个过程

3、隔离级别
  • 读未提交:事务可以读到其他事务还没提交的数据
  • 读已提交:事务只能读到其他事务已经提交的数据,也就是说,一个事务在提交之前,它所做的修改对于其他的事务来说是不可见的
  • 可重复读:保证在同一个事务中多次读取同一数据的结果是一样的
  • 可串行化:事务串行化执行,这样互不干扰,就不会产生一致性问题。这个隔离级别需要加锁实现
4、MVCC

多版本并发控制是MySql的InnoDB引擎实现隔离级别的一种具体方式
主要实现了读已提交和可重复读两种隔离级别,默认的隔离级别是可重复读
读未提交每次都读最新的数据,无需MVCC
可串行化需要加锁,光靠MVCC做不到

  • 行格式
    行格式就是InnoDB 在保存每一行的数据的时候,究竟是以什么样的格式来保存这行数据的

    真实数据列部分中,列1…列N是我们存储的正常数据,除此之外
    DB_ROW_ID是行id,用来唯一标识一行数据
    DB_TRX_ID是事务id,表示了当前行是被哪个事务修改的。当一个事务开启的时候,会分配到一个事务id,这个id是严格单调递增且唯一的
    DB_ROLL_PTR是回滚指针,它指向一条undo log的地址,通过这条undo log,可以使这行数据恢复到上一个版本
  • MVCC
    核心思想:保存数据库行的历史版本,通过对数据行的多个版本进行管理来实现对数据库的版本控制,换句话说,每个数据库行是有多个历史版本的
    精髓在下图,绿色箭头相当于undo log,可以恢复出数据行的历史版本

    接下来结合两个隔离级别来说明这个图
    1、可重复读
    当我们开启一个事务的时候,会申请到一个事务id,同时在事务开启的一瞬间会生成一个数组,这个数组记录了此时活跃的事务id,也就是已开启还未提交的事务
    当当前事务想要去查看某一行数据的时候,会先看那行数据的DB_TRX_ID:
  • 如果DB_TRX_ID等于当前事务id:说明这行数据就是当前事务修改的,数据可见
  • 如果DB_TRX_ID小于数组的最小值:说明在当前事务开启之前,这条数据已经提交了,那数据就是可见的
  • 如果DB_TRX_ID大于数组的最大值:说明修改这条数据的事务是在当前事务开启后才开启的,那数据就不可见
  • 如果DB_TRX_ID的值在数组最大值和最小值之间,但不在数组中:说明这条数据是被和当前事务同时活跃的,但是提交的早的事务修改的,所以数据可见
  • 如果DB_TRX_ID的值在数组最大值和最小值之间,但不在数组中:说明修改数据的事务还没提交,数据不可见

当数据不可见的时候,就沿着undo log恢复上一个版本,进行上面的判断
2、读已提交
和可重复读是类似的,只是它会在执行每一个语句前生成这个数组,也就是一致性视图
3、MVCC的注意点
注意MVCC不是完全不加锁,只是避免了select操作时的加锁
读的时候使用了快照读和上面的一致性视图,
写的时候使用的是当前读,而不是快照读,这样也避免了丢失修改
在一定程度上实现了读写并发控制,读写互不阻塞

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/861104.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号