本地事务总结 篇
in sqlCo-De with 0 comment

本地事务总结 篇

in sqlCo-De with 0 comment

本地事务总结

GOAL:ACID

Atomicity

Transactions are often composed of multiple statements. Atomicity guarantees that each transaction is treated as a single "unit", which either succeeds completely or fails completely: if any of the statements constituting a transaction fails to complete, the entire transaction fails and the database is left unchanged.

Consistency

Consistency ensures that a transaction can only bring the database from one consistent state to another, preserving database invariants

Isolation

Transactions are often executed concurrently (e.g., multiple transactions reading and writing to a table at the same time). Isolation ensures that concurrent execution of transactions leaves the database in the same state that would have been obtained if the transactions were executed sequentially.

Durability

Durability guarantees that once a transaction has been committed, it will remain committed even in the case of a system failure (e.g., power outage or crash.

Local Transaction

定义

本地事务/局部事务,是基础的事务解决方案。单个服务使用单个数据源。

依赖数据库本身的事务能力,比如开启,终止,提交,回滚,隔离级别等,如果数据库本身不具备,则无法提供相应的能力,比如MyISAM没有rollback

ARIES原理

基于语义的恢复与隔离算法,实现原子性(A),持久性(D),提供隔离性(I)

A和D

原因

数据需要写入磁盘等持久化存储,如果突然断电或者宕机,会造成数据丢失,即Crash

写入磁盘本身存在未写入,写入中,写入完成等状态,其中写入中为中间状态

  1. 未提交事务,写入后崩溃:修改3条数据,2条已经写入磁盘,剩余1条未写入。需要回滚,保证原子性。
  2. 已提交事务,写入前崩溃:修改3条数据,均未写入磁盘,崩溃。需要能够重新写入,保证持久性。

解决

由于Crash是不可避免的,所以需要Crash Recovery进行补偿

Commit Logging

提交日志:修改数据的操作需要的全部信息以日志的形式,顺序追加记录。成功提交的记录,追加日志(提交记录,Commit Record),数据库根据提交记录进行数据存储操作,完成后,追加日志(记录结束,End Record)。

  1. 有提交记录,没有记录结束: 持久性,顺序执行数据存储
  2. 有操作记录,无提交记录:原子性,执行数据回滚

性能问题:事务提交之前,不允许修改磁盘数据,如果修改数据量大,占用大量缓存区,不利于提升数据库性能。

Write Ahead Logging(ARIES)

提前写入:允许事物提交之前,写入变动数据

写入时机:

  1. FORCE:日志与磁盘写入同时完成。默认NO-FORCE,基于日志,可以随时写入
  2. STEAL:允许提前写入,充分利用磁盘IO

CommitLogging 允许no-force,但是不需要steal

WAL 增加额外的Undo Log,Redo Log,实现no-force + steal

  1. UNDO LOG:写入磁盘前,记录什么数据,从什么修改为什么等,用于Crash时,进行数据回滚/擦除
  2. Redo LOG:重演数据变动,持久性

恢复步骤:

  1. 分析阶段:从最后一次检查点(CheckPoint)扫描日志,获取所有没有记录结束(End Record)的日志事务,形成待恢复事务集合,包括Transaction Table,Dirty Page Table
  2. 重做Redo:Repeat History,找出所有的Commit Record,然后顺序写入磁盘,然后追加End Record
  3. 回滚Undo:剩下的事物日志(未Commit的)属于待回滚的(Loser),根据Undo Log中信息,将已经写入的信息,修改回去,完成回滚。

Redo和Undo都需要支持幂等,复杂的数据结构,主要来自ARIES的论文。

从优化磁盘 I/O 的角度看,NO-FORCE 加 STEAL 组合的性能无疑是最高的;从算法实现与日志的角度看 NO-FORCE 加 STEAL 组合的复杂度无疑也是最高的

image-20230626184530-ceknx1d.png

Shadow Paging

数据的变动会写到硬盘的数据中,但并不是直接就地修改原先的数据,而是先将数据复制一份副本,保留原数据,修改副本数据。

在事务过程中,被修改的数据会同时存在两份,一份是修改前的数据,一份是修改后的数据,这也是“影子”(Shadow)这个名字的由来。

当事务成功提交,所有数据的修改都成功持久化之后,最后一步是去修改数据的引用指针,将引用从原数据改为新复制出来修改后的副本,最后的“修改指针”这个操作将被认为是原子操作,现代磁盘的写操作可以认为在硬件上保证了不会出现“改了半个值”的现象。

Shadow Paging 也可以保证原子性和持久性。Shadow Paging 实现事务要比 Commit Logging 更加简单,但涉及隔离性与并发锁时,Shadow Paging 实现的事务并发能力就相对有限,因此在高性能的数据库中应用不多。

I

原因

多个事物读写同一个数据的时候,会存在并发的可能,需要保证各个事务独立,不互相影响的同时,还要保证数据使用上的一致,所以需要实现数据库事务的隔离性。

隔离级别

串行化SE

可重复读RR(幻读)

读已提交RC(不可重复读)

读未提交RU(脏读)

LBCC - 基于锁的并发控制

RU

RC

RR

SE

问题

基于锁来实现数据库的隔离机制,主要是通过排他来进行阻塞,保证数据多次查询的一致。但是加锁的代价很高,例如RC时,select操作需要添加瞬时的共享锁,加解锁频繁,效率低

MVCC - 基于版本的并发控制(Mysql)

事务版本属性

每次事务会生成一个递增的事务ID,每行数据扩展两个属性,操作事务ID,回滚指针(Undo Log)

查询:数据的操作事务ID <= 当前事务ID

新增:数据的操作事物ID -> 当前事务ID,回滚指针 -> null

删除:数据变化写入Undo Log,操作事务ID -> 当前事务ID,回滚指针 -> Undo Log,标记删除 -> 当前事务ID,purge后物理删除

更新:数据变化写入Undo Log,数据的更新,操作事务ID -> 当前事务ID,回滚指针 -> Undo Log

Read View 读视图

快照读:查询操作(Select)通过读视图进行,不加锁

当前读:新增,更新,删除操作(insert,update,delete)加锁,使用最新数据

读视图提供:

版本控制判断

RU

RC

RR

SE

Comments are closed.