事务

主要整理总结关于事务以及事务处理技术,数据库恢复以及并发控制所带来的问题。


事务:

一系列数据库操作,是数据库应用程序的基本逻辑单元。
事务是恢复和并发控制的基本单位

在关系型数据库中,一个事务可以是一条SQL语句、一组SQL语句或整个程序。

对于事务和程序的区别主要在于:一个程序中包含多个事务。

定义事务的语句一般有三条:

BEGIN TRANSACTION;          //开始
COMMIT;                     //提交
ROLLBACK;                   //回滚

COMMIT:表示提交,即提交事物的所有操作.也就是将事务中的更新写回到磁盘上的物理数据库中,事务正常结束。
ROLLBACK:表示回滚,即在事务运行的过程中发生某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作(更新操作)全部撤销,回滚到事务开始时的状态。

事务是恢复和并发控制的基本单位。
保证事物ACID特性是事务管理的重要任务。

ACID特性

  1. 原子性:事务是数据的逻辑工作单位,事务中的操作要么都做,要么都不做。
  2. 一致性:事务执行的结果必须是使数据库从一个一致性状态到另一个一致性状态。
  3. 隔离性:一个事物的执行不被其它事务干扰,即并发执行的各个事务之间不能相互干扰。
  4. 持续性(永久性):一个事务一旦提交,它对数据库的改变就是永久性的。

ACID特性可能遭到破坏的因素有;

  • 多个事务并行运行时,不同事务的操作交叉执行;
  • 事务在运行过程中被强制停止。

为保证数据库的安全性和完整性,事物的正确执行,在发生故障的情况下,数据库能够从错误状态恢复到某一已知的正确状态。恢复子系统时数据库管理系统的一个重要组成部分。


故障

主要有事物内部故障、系统故障、介质故障和病毒。

  1. 事物内部的故障:有些可通过事务程序本身发现,更多的是非预期的,不能由应用程序处理的。如运算溢出、并发事务发生死锁而被选中撤销该事务、违反了某些完整性限制而被终止等。
    事务故障意味着事务没有达到重点(COMMIT或显示的ROLLBACK),因此数据库处于不正确状态。可通过事务撤销(UNDO),强行回滚该事务。
  2. 系统故障(软故障):是指造成系统停止运转的任何事件,使得系统要重新启动。
    一些故障是影响正在运行的所有事物,但不破坏数据库,尤其是数据库缓冲区(在内存)中的内容被丢失。可清除事务对数据库的所欲修改。
    另一方面,发生系统故障,有些已完成的事务可能有一部分甚至全部留在缓冲区,尚未写回到磁盘上的物理数据库中,使得事务对数据库的修改部分或全部丢失。可通过重做(REDO),将已提交的结果重新写入数据库。
  3. 介质故障(硬故障):破坏数据库或部分数据库,并影响正在存取这部分数据的所有事物。
  4. 计算机病毒:人为的故障或破坏。

硬故障和软故障区别

  • 硬故障是指外村故障,如磁盘损坏、磁头碰撞、瞬时强磁场干扰等。
  • 软故障是指系统故障,特定类型的硬件错误(CPU故障)、操作系统故障、DBMS代码错误以及系统断电等。
  • 硬故障主要破坏数据库或部分数据库并影响正在存取这部分内容的所有事物;软故障影响正在运行的所有事务,但不破坏数据库。
  • 软故障发生的可能性比硬故障小,但破坏性很大。

数据库恢复——冗余

建立冗余数据主要通过数据转储和登记日志文件。

1.数据转储
所谓转储即数据库管理员定期将整个数据库复制到磁带、磁盘或其他存储介质上保存起来。
这些备用的数据称为后备副本。
当数据库遭到破坏后可以将后备副本重新装入,但重装后备副本只能将数据库恢复到转储时的状态;要想恢复到故障发生时的状态,必须重新运行自转储以后的所有更新事务。    

这里写图片描述

这里写图片描述
- 静态转储:在系统中无运行事务时进行的转储操作,即转储期间不允许对数据库的任何存取、修改活动。但必须等待正在运行的用户事务结束才能进行,同样新的事物必须等待转储结束才能执行。缺点是会降低数据库的可用性。
- 动态转储转储期间允许用户对数据库进行存取或修改。即转储和用户事务可以并发执行。不用等待正在运行的用户事务结束,也不会影响新事物的运行。
但是,转储结束后备副本上的数据不能保证正确有效。可通过建立日志文件,把转储期间各事务对数据库的修改活动登记下来。
- 海量转储:每次转出全部数据库
- 增量转储:每次只转储上一次转储后更新过的数据。

2.登记日志文件
之前在博客中也提到了了日志,建立冗余数据的第二个技术就是登记日志文件。
日志文件是用来记录事务对数据库的更新操作的文件。
日志文件的作用:

  1. 事务故障恢复和系统故障必须用日志文件
  2. 在动态转储中必须建立日志文件,后本副本和日志文件结合起来才能有效的恢复数据库
  3. 在静态转储中建立日志文件,当数据库毁坏后可重新装入后备副本把数据库恢复到转储结束时刻的正确状态,然后利用日志文件把已完成的事务进行重做处理,对故障发生时尚未完成事务进行撤销处理。
    这里写图片描述

为保证数据库可恢复,登记日志文件时必须遵循两条原则:

  • 登记的次序严格按照并发事务执行的时间次序
  • 必须先写日志文件,后写数据库

分布式事务

分布式事务指的是允许多个独立的事务资源参与了一个全局的事务中

  • 资源管理器:提供访问事务资源的方法。一般由数据库实现
  • 事务管理器:作为全局的调度者,协调参与全局事务中的各个事务,负责各个本地资源的提交和回滚。需要和参与全局事务中的所有资源管理器进行通讯。
  • 应用程序:定义事务的边界,指定全局事务中的操作。

事务资源通常是关系型数据库系统,也可以是其他类型的资源。全局事务要求在其中所有参与的事物要么都提交、要么都会滚,这对于事物的ACID要求又有了提高。

InnoDB存储引擎支持XA事务,通过XA事务可以支持分布式事务的实现。
XA事务,是指分布式事务协议,即事务管理器和本地资源管理器。
下图为XA事务的两阶段:

这里写图片描述


并发控制

事务是并发控制的基本单位。为保证事物的隔离性和一致性,数据库管理系统需要对并发控制进行正确的调度。

并发控制带来的数据不一致有:

  1. 丢失修改
  2. 不可重复读:在一个事务内多次读同一数据。
  3. 读”脏“数据:即不正确的数据

脏数据和脏页:
脏页,是指在缓冲池中已经被修改的页,但是还没有刷新到磁盘,即数据库实例内存中的页和磁盘中的页的数据是不一致的。
脏数据,是指在缓冲池中被修改的数据,并且没有被提交(commit)。
区别:

  • 脏页是由于数据库实例内存和磁盘的异步同步造成的,不影响数据的一致性。且因为是异步的,可以带来性能的提高。
  • 脏数据是指未提交的数据。如果都到了脏数据,即一个事务可以读到另一个事务中未提交的数据,则违反了数据库的隔离性。
  • 脏读是在不同事务下,可以读到另外事务未提交的数据。也就是可以读到脏数据。
  • 脏读是读到未提交的数据;不可重复读的是已经提交的数据,违反了事务的一致性。

并发控制的主要技术有封锁、时间戳、客观控制法和多版本并发控制。接下来分别看一下

1.封锁

SQL Serve下的封锁类型有两种:

  • 排他锁(X锁):又称写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事物都不能再对A加任何锁。
  • 共享锁(S锁):又称读锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁为止。

InnoDB存储引擎的行锁是通过给索引项加锁来实现;而MySQL与Oracle是通过在数据库中对相应数据行加锁来实现。

InnoDB只有通过索引条件检索数据,才会使用行级锁;否则,将使用表锁

MySQL的行锁是针对索引加的锁,不是针对记录加的。


InnoDB下的间隙锁(Next-Key锁)

当用范围条件而不是想等条件减锁数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但不存在的记录,记作“间隙”。
例如,emp表中只有101条记录,其empid的值分别是1,2,….100,101,下面的SQL:

//范围条件检索
Select* from rmp where empid > 100 for update;
InnoDB不仅会对符合条件的empid的值为101的记录加锁,也会对empid大于101(不存在 
的记录)的“间隙”加锁。

InnoDB使用间隙锁的目的:

一方面是为了防止幻读,以满足相关隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了大于100的记录,那么这个事务再次执行上述语句,就会发生幻读;
另一方面,是为了满足其恢复和复制的需要。

MySQL的恢复机制要求:在一个事务未调教前,其他并发事务不能插入满足其锁定条件的任何记录,也就是不允许出现幻读。要求事务要串行化。


2.活锁和死锁

活锁: 事务1可以使用资源,但它让其他事务先使用资源;事务2可以使用资源,但它也让其他事务先使用资源,于是两者一直谦让等待,都无法使用资源。

死锁:会话A和会话B的资源互相在等待。如果事务T1封锁了数据R1,T2封锁了数据R2,然后T1又请求封锁R2,因T2已封锁了R2,于是T1等待T2释放R2上的锁。接着T2又申请封锁R1,因T1已封锁了R1,T2也只能等待T1释放R1上的锁。这样就出现了T1在等待T2,而T2又在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。

InnoDB存储引擎可以自动检测到死锁,不需要人为干预。发现死锁后,会立即回滚一个事务。
Oracle数据库中产生死锁的原因是没有对外键添加索引,而InnoDB会自动对其进行添加。

锁升级

锁升级就是将当前锁的粒度降低。
例如,数据库可以把一个表的1000个行锁升级为一个页锁,或者将页锁升级为表锁。
SQL Server会自动地将行、键或者分页级为更粗粒度地表级锁。这种升级保护了系统资源,防止系统使用太多的内存来维护锁,从一定程度上提高了效率。

锁粒度的降低而导致并发性能的降低
但是,InnoDB存储引擎不存在锁升级的问题。在InnoDB存储引擎中,1个锁的开销与1000000个锁是一样的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值