数据库本地事务的实现原理

什么是事务:

一句话:事务就是要么全做。要么全不做。ALL OR NOTHING

官方一点:事务提供了一种机制,把一个活动中的所有操作纳入到一个不可分割的单元,事务中的所有操作只有在所有操作全部正常执行的情况下方才能提交,只要其中有任一操作执行失败,都将导致整个事务的回滚到事务开始前的状态,

事务四大特性:ACID

A:原子性(Atomicity),一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态

C:一致性(Consistency),指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。

I:隔离性(Isolation),指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

数据库锁:

1、按级别(操作)分

共享锁(读锁):针对同一块数据,多个读操作可以同时进行而不会互相影响。是只能读不能修改。

排他锁(写锁):排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。当前写操作没有完成前,阻断其他写锁和读锁。

2、按粒度分

行级锁:开销大,加锁慢,会出现死锁,锁定力度最小,发生锁冲突的概率最低,并发度高。
表级锁:开销小,加锁快,不会出现死锁,锁定力度大,发生冲突所的概率高,并发度低。
页面锁:开销和加锁时间介于表锁和行锁之间,会出现死锁,锁定力度介于表和行级锁之间,并发度一般。

事务的实现原理:

数据库不同的存储引擎可能会有一些区别。这里拿常用的InnerDB存储引擎举例:

1、原子性实现原理:

通过数据库Undo Log实现的。事务中在操作任何数据之前,首先将原数据备份到Undo Log然后进行数据的修改。如果事务中有任意操作发生异常或用户执行了 Rollback 语句,那么数据库就会使用Undo Log中的备份将数据恢复到事务开始之前的状态。 

2、一致性实现原理:

与原子性实现原理一样也是利用Undo Log

3、持久性实现原理:

通过数据库Redo Log实现的,Redo Log与Undo Log 相反,Redo Log 记录的是新数据的备份,事务提交之前,会把数据备份到Redo Log中并持久化。当系统崩溃时,虽然数据没有持久化到数据库中,但是 Redo Log 已经持久化。系统可以根据 Redo Log 的内容,将所有数据恢复到最新的

4、隔离性实现原理:

隔离性的实现原理比较特殊,是通过数据库锁的机制实现的。

隔离性分四个级别:读未提交(Read uncommitted)、读已提交(Read committed)、可重复读(Repeatable reads)、可序列化(Serializable)

MySQL的默认隔离级别就是Repeatable,Oracle默认Read committed

4.1、读未提交:一个事务可以读到另外一个事务未提交的数据。脏读

实现:事务在读数据的时候并未对数据进行加锁。

           事务在发生更新数据的瞬间,必须先对其加 行级共享锁,直到事务结束才释放。

举例:事务A读取某行记录时(没有加锁),事务2也能对这行记录进行读取、更新。当事务B对该记录进行更新时,事务A读取该记录,能读到事务B对该记录的修改版本,即使该修改尚未被提交。

 事务A更新某行记录时,事务B不能对这行记录做更新,直到事务A结束。

4.2、读已提交:一个事务可以读到另外一个事务提交的数据。不可重复读

实现:事务对当前被读取的数据加 行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁;

           事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。

原理:事务A读取某行记录时,事务B也能对这行记录进行读取、更新;当事务B对该记录进行更新时,事务A再次读取该记录,读到的只能是事务B对其更新前的版本,或者事务B提交后的版本。

事务A更新某行记录时,事务B不能对这行记录做更新,直到事务1结束

流程描述:事务A读操作会加上共享锁,事务B写操作时会加上排他锁,当事务B正在写操作时,事务A要读操作,发现有排他锁,事务A就会阻塞,等待排他锁释放(事务B写操作提交才会释放),才能进行读操作。

4.3、可重复读

实现:事务在读取某数据的瞬间(就是开始读取的瞬间),必须先对其加 行级共享锁,直到事务结束才释放;

           事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。

举例:事务A读取某行记录时,事务B也能对这行记录进行读取、更新;当事务B对该记录进行更新时,事务A再次读取该记录,读到的仍然是第一次读取的那个版本。

事务A更新某行记录时,事务B不能对这行记录做更新,直到事务1结束。

4.4、可序列化(Serializable) 写操作串联执行

实现:事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;

事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。

举例:

事务A正在读取A表中的记录时,则事务B也能读取A表,但不能对A表做更新、新增、删除,直到事务A结束。

事务A正在更新A表中的记录时,则事务B不能读取A表的任意记录,更不可能对A表做更新、新增、删除,直到事务A结束。

原理:在读操作时,加表级共享锁,事务结束时释放;写操作时候,加表级独占锁,事务结束时释放。

并行事务的四大问题:

1、脏读(如有事务A和B,A读取了B未提交的数据)

2、不可重复读(如有事务A和B,A负责读取,B负责写入,A连续读的过程中B写入了一次,A前后两次读出来的数据不一样)

3、丢失更新(如有事务A和B,AB均写入数据,A写入的数据被B覆盖)

4、幻读(如有事务A和B,A修改表内数据的过程中,B向表内插入了一条数据,A修改完后发现数据并没有被全部修改完)
 

 

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值