数据库基础干货数据库事务

Posted 在路上的德尔菲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库基础干货数据库事务相关的知识,希望对你有一定的参考价值。

数据库事务

A原子性(Atomicity)

一个事务里包含5条SQL语句,要么全部执行成功,要么全部执行失败,如果执行一半失败了需要回滚
在操作任何数据之前,首先将数据备份到undolog(回滚日志) 然后进行数据修改,如果出现错误或用户回滚,利用undolog中备份恢复到事务开始之前的状态
⚠️如果执行insert操作,undolog中相对应增加一条delete语句,同理update 2-5,undolog增加5-2

C一致性(Consistency)

原子性、隔离性、持久性是为了保证一致性

I隔离性(Isolation)

并发事务执行时互不干扰,等价于这些事务串行顺序跑,
常见的隔离级别为:读未提交、读已提交、可重复度、串行化

  • 读未提交 无法解决脏读
  • 读已提交 可以解决脏读(Oracle 默认级别)
  • 可重复读 可以解决不可重复读*(更新)* (mysql默认事务隔离级别)
  • 可串行化 可以解决幻读问题*(插入)*

D持久性(Durability)

事务一旦提交,对数据库的更新就是持久的,由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复

持久化存储,

  • 尽快落盘,在写入核心数据结构之前,需要先写事务log,MySQL InnoDB称为redo log,即使数据库挂了,重启恢复数据时,必须先从log中redo,为了吞吐量,可以配置每隔一段时间/事务刷盘,意味着系统挂掉会丢失一部分事务
  • 复制,对数据尽可能多的副本,failover应对机器挂掉的风险

为了防止事务两次读取的数据不一致(包括不可重复读和幻读)
采用MVCC处理读写冲突的情况,不同的事务在并发过程中,SELECT操作可以在不加锁而是通过MVCC的机制读取指定版本的历史记录,MVCC是MySQL InnoDB实现隔离级别的一种方式
常见并发事务过程存在的问题:脏读、不可重复度、幻读,实现隔离机制方法一般有两种

  1. 加读写锁
  2. MVCC,指的是多个版本快照,快照存储在undo日志中,该日志通过回滚指针 ROLL_PTR 把一个数据行的所有快照连接起来

MySQL中MVCC的实现

  • MySQL中InnoDB引擎默认支持MVCC,读写早期只有读读阻塞,读写、写读、写写都要阻塞,引入MVCC后只有写写阻塞
  • 应对高并发事务,MVCC比单纯的加行锁更有效,开销更小,普通的SELECT读对数据库不会对数据加锁,提高了数据库并发处理能力
  • MVCC在 读已提交 和 可重复读隔离级别下起作用:而未提交读隔离级别总是读取最新的数据行,要求很低,无需使用 MVCC。可串行化隔离级别需要对所有读取的行都加锁,单纯使用 MVCC 无法实现,在可重复读隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。(MySQL隔离级别为幻读的特殊处理)
  • MVCC 既可以基于乐观锁又可以基于悲观锁实现

InnoDB每一行数据都有两个隐藏列:ID为隐含ID,DATA_TRX_ID记录更新这条行记录的事务ID、DATA_ROLL_PTR指向回滚段的指针,通过这个指针找到之前版本ID,就可以找到之前行数据

undolog与redolog

  • undolog 有时事务需要撤销,这时需要进行undo,当有错误或回滚时,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可恢复之前版本。
  • redolog(前滚日志) 方便通过其进行重做,在事务执行时,往InnoDB日志缓存(log buffer)中插入redolog;事务提交时,将日志缓冲写入磁盘。系统发生奔溃可以用重做日志(Redo Log)进行恢复,从而实现持久性。类比赊账本,先写进redolog,然后循环写方式持久化

举个栗子:
假设有A、B两个数据,值分别为1、2,开启事务分别对其进行修改A → 3,B → 4,在提交,过程如下:
事务开始
记录A=3到redo log
修改A=3
记录A=1到undo log
记录B=4到redo log
修改B=4
记录B=2到undo log
将redo log写入磁盘
事务提交

几种Locks

  • Record Locks:锁定一个记录上的索引,而不是记录本身。如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks 依然可以使用。
  • Gap Locks:锁定索引之间的间隙,但是不包含索引本身,当执行以下操作时,其他事物不能向库表中插入15
SELECT c FROM t WHERE c BETWEEN 10 and 20 FOR UPDATE;
  • Next-Key Locks间隙锁:是 Record Locks 和 Gap Locks 的结合,不仅锁定一个记录上的索引,也锁定索引之间的间隙。它锁定一个前开后闭区间

以上是关于数据库基础干货数据库事务的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL事务超全知识总结#yyds干货盘点#

#yyds干货盘点#HBase 基础及核心架构解析

每日干货:简说Spring事务

如何绕过将数据模型传递给片段参数以避免事务太大异常?

回栈事务后如何持久化分片数据?

干货Kafka 事务特性分析