数据库事务、隔离等级、锁

 

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

 

  • 事务的ACID特性

 

原子性Automicity:一个事务内的所有操作,要么全做,要么全不做

一致性Consistency:数据库从一个一致性状态转到另一个一致性状态

隔离性Isolation: 一个事务在执行期间,对于其他事务来说是不可见的

持久性Durability: 事务一旦成功提交,则就会永久性的对数据库进行了修改

(一致性这个可能会稍微难理解点,如果没有进行插入或者删除操作,只进行Update操作,那么一致性和能量守恒定律有些类似,另外可参考https://segmentfault.com/q/1010000005984017这篇博文)

  • 隔离等级

 

 

脏读: 事务可以读取未提交的数据,比如:

事务A对某一个数据data=1000 进行了修改: data = 2000, 但是还没有提交;

事务B读取data 得到了结果data = 2000,

由于某种原因事务A撤销了刚才的操作,数据data = 1000 然后提交

这时事务B读取到的2000就是脏数据。正确的数据应该还是 1000

解决方法 : 把数据库的事务隔离级别调整到READ_COMMITTED , 但是存在事务A与B都读取了data,A还未完成事务,B此时修改了数据data,并提交, A又读取了data,发现data不一致了,出现了不可重复读。

不可重复读 在同一个事务之中,多次读取相同的记录的值的结果是不一样的,针对的是数据的修改和删除。

事务A 读取data = 1000, 事务还未完成;

事务B 修改了data = 2000, 修改完毕事务提交;

事务A 再次读取data, 发现data = 2000 了,与之前的读取不一致的

解决办法; 把数据库的事务隔离级别调整到 REPEATABLE READ , 读取时候不允许其他事务修改该数据,不管数据在事务过程中读取多少次,数据都是一致的,避免了不可重复读问题

幻读: 当某个事务在读取某个范围内的记录的时候,另外一个事务在这个范围内增加了一行,当前一个事务再次读取该范围的数据的时候就会发生幻行,. 针对的是数据的插入insert

解决方案 : 采用的是范围锁 RangeS RangeS_S模式,锁定检索范围为只读 或者 把数据库的事务隔离级别调整到SERIALIZABLE_READMySQL中InnoDB 和 XtraDB 利用(多版本并发控制)解决了幻读问题

 

  • 加锁协议

一次封锁协议因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会用到哪些数据,然后全部锁住,在方法运行之后,再全部解锁。这种方式可以有效的避免循环死锁,但在数据库中却不适用,因为在事务开始阶段,数据库并不知道会用到哪些数据

两段锁协议 将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁)

 

1. 加锁阶段在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁(只有当前数据无共享锁,无排它锁之后才能获得),其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。

 

2. 解锁阶段当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。

事务提交时(commit) 和事务回滚时(rollback)会自动的同时释放该事务所加的insert、update、delete对应的锁。

这种方式虽然无法避免死锁,但是两段锁协议可以保证事务的并发调度是串行化(串行化很重要,尤其是在数据恢复和备份的时候)的。

 

  • 死锁

指两个事务或者多个事务在同一资源上相互占用,并请求对方所占用的资源,从而造成恶性循环的现象。

 

出现死锁的原因:

1. 系统资源不足

2. 进程运行推进的顺序不当

3. 资源分配不当

 

产生死锁的四个必要条件

1. 互斥条件: 一个资源只能被一个进程使用

2. 请求和保持条件:进行获得一定资源,又对其他资源发起了请求,但是其他资源被其他线程占用,请求阻塞,但是也不会释放自己占用的资源。

3. 不可剥夺条件: 指进程所获得的资源,不可能被其他进程剥夺,只能自己释放

4. 循环等待条件: 进程发生死锁,必然存在着进程-资源之间的环形链

处理死锁的方法: 预防,避免,检查,解除死锁

 

死锁预防

我们可以通过破坏死锁产生的4个必要条件来 预防死锁,由于资源互斥是资源使用的固有特性是无法改变的。

  1. 破坏“不可剥夺”条件:一个进程不能获得所需要的全部资源时便处于等待状态,等待期间他占有的资源将被隐式的释放重新加入到 系统的资源列表中,可以被其他的进程使用,而等待的进程只有重新获得自己原有的资源以及新申请的资源才可以重新启动,执行。

  2. 破坏”请求与保持条件“:第一种方法静态分配即每个进程在开始执行时就申请他所需要的全部资源。第二种是动态分配即每个进程在申请所需要的资源时他本身不占用系统资源。

  3. 破坏“循环等待”条件:采用资源有序分配其基本思想是将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的进程才能申请较大编号的进程

死锁避免

死锁避免的基本思想:系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,如果分配后系统可能发生死锁,则不予分配,否则予以分配,这是一种保证系统不进入死锁状态的动态策略。

如果操作系统能保证所有进程在有限时间内得到需要的全部资源,则系统处于安全状态否则系统是不安全的。

 

银行家算法: 思想:

当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量。若超过则拒绝分配资源,若没有超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前的申请量分配资源,否则也要推迟分配

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值