zoukankan      html  css  js  c++  java
  • 数据库基本概念之事务与并发控制

    数据库基本概念之事务与并发控制

    • 事务ACID

    参考资料:关系数据库工作原理简述

    数据库事务具有ACID特性

    「为什么引入原子性」事务执行过程中可能是不一致的状态,如果能确保事务原子性,除了执行过程中,其它时刻不一致性状态都是不可见的。通过记录redo/undo日志-通过

    • 原子性(Atomicity):数据库事务包含的所有操作,要么全部执行成功,要么完全不执行。执行成功的操作写入数据库,一旦执行失败对数据库没有任何影响。
    • 一致性(Consistency):数据库在事务执行前和执行后都是一致性的状态,即事务的执行是从一个一致性状态转换至另一个一致性状态「完整性约束」
    • 隔离性(Isolation):数据库应该保证:事务不应该读取其他事务产生的不一致的中间数据,因为这样会导致对数据库的错误更新。即,每个事务都感觉不到其它事务在并发的执行。
    • 持久性(Durability):事务执行成功,它对数据库的改变将是永久的--数据库发生故障不应该影响已经成功之行的事务。

    事务调度

    调度:多个事务的中操作的一个CPU执行顺序。

    可串行化调度:如果存在调度S1,使得无论什么数据库初态,调度S1、S效果相同,那么S是可串行化的。

    两个事务操作Ii,Ij分别属于事务Ti,Tj冲突的条件

    1. 操作Ii,Ij位于不同事务中,即:i!=j
    2. 操作面向同一个数据对象
    3. 两个操作中至少有一个为写

    若调度S经过若干非冲突操作的交换,得到调度S1,那么S和S1是冲突等价的,若S为串行调度则称S1为冲突可串行化。

    调度S与S1称为视图可串行化,当满足如下条件:

    1. 任意数据项Q,调度S中是Ti读取了初始值,那么调度S1中也是Ti读取了初始值
    2. 任意数据项Q,调度S中Ti读取了Tj写入的数据,那么S1中也必须是Ti读取了Tj写入的数据
    3. 任意数据项Q,调度S中Ti完成最后写,那么S1中也必须是Ti完成最后写

    视图可串行化比冲突可串行化更宽松一点,任意一个视图可串行化非冲突可串行化的调度中,肯定存在盲写(即不读直接写)。级联回滚是由于脏读引起的,避免级联回滚读已提交。如果仍然是读未提交级别的话,需要满足当前事务读的数据的创造者早于。

    为什么要引入锁?防止多个事务并发执行时:同时对数据库元素读/写导致非可串行化发生。临界区

    如果在访问数据完成立即释放锁,将会导致不一致的情况发生。例如:

    T1: X(A)R(A)(A+=50)W(A)U(A)X(B)R(B)(B-=50)W(B)U(B)
    T2: S(A)R(A)U(A)S(B)R(B)U(B)display(A+B)

    事务执行过程中,SET A、B 100,执行结果可能是250,也可能是150,造成了数据库的不一致性。

    若假定事务约定提交时候才释放锁,那么会导致死锁的产生。例如:

    T1: W(A)W(B)
    T2: W(B)W(A)

    在事务T1执行完W(A),需要在B上加X锁才能释放在A上的锁,T2需要在A上加X锁才能释放B上的排他锁,这就导致一个死锁的发生。Ti->Tj表示Tj等待Ti持有的锁,假如等待图中出现环,即表示发生死锁,需回滚其中一个事务才能解决。

    饿死: T1持有A上的S锁,T2要在A上加X锁,如果再有事务在A上加S锁,都会排在T2之前,就会导致T2总是不能加排他锁。避免的条件(T要在Q上加M锁):

    1. 不存在其它事务持有Q上与M冲突的锁
    2. 等待队列中不存在先于T的事务(先后顺序)

    避免死锁的措施:T2需要在Q上加锁,如果Q的等待队列中存在T1,T1需要持有T2已持有的锁,那么把T2放在T1前边。

    • 两阶段封锁(two phase lock,2PL):即在释放锁之前必须把其他的锁都加上。是实现可串行化的充分条件。
    • 严格两阶段封锁协议:事务持有的排他锁在事务执行结束才释放
    • 强两阶段封锁协议:事务提交之前不得释放任何锁

    更新锁:两个事务先加共享锁,然后两个事务都想升级锁,导致的经典死锁问题,更新锁加锁时自己和S一样,已持有后,更排他锁一样

    警示锁:用在数据库元素多层次上,IS IX S X对子元素上锁是,必须先对父元素上锁

    幻读 :将insert、delete设计成对数据库表粒度的写操作

    T1
    BEGIN
    select count(*) from table1 where id = 1;
    *****           <--
    end;
    
    begin;
    insert into table(id) values(1);
    end;
    

    以上例子T1首先对表中所有元组加S锁,正在计算还未提交,事务T2插入了一条符号条件的,但是被漏掉了~

    树形结构封锁:例子,索引文件的索引块

    • 事务第一个锁可以在树的任意节点上
    • 只有事务当前节点的父节点持有锁时才能获得后续的锁
    • 节点可以任意时候释放锁
    • 事务不能对一个解锁的事务重新上锁,即使改节点在其父节点上仍然持有锁(不能回头)

    有效性确认:

    • 对于所有经过有效性验证且在T开始前没有完成的U,即满足FIN(U)>START(T),检测WS(T) WS(U)是否有交叉。
    • 对于已经经过有效性验证且在T有效性验证前没有完成的U,
  • 相关阅读:
    c++ 设计模式3 (重构技法 Template Method)
    C++ 设计模式2 (面向对象设计原则)
    c++ 设计模式1
    算法总结—二分搜索与旋转排序数组
    c++ 构造函数,拷贝构造函数,析构函数与赋值操作符
    题解 P2330 【[SCOI2005]繁忙的都市】
    题解 CF896C 【Willem, Chtholly and Seniorious】
    题解 P3369 【【模板】普通平衡树】
    题解 CF383C 【Propagating tree】
    题解 P1179 【数字统计】
  • 原文地址:https://www.cnblogs.com/bingo711x/p/6438059.html
Copyright © 2011-2022 走看看