精华内容
下载资源
问答
  • 两阶段封锁协议
    2022-03-23 15:54:40

    两阶段锁协议

    在数据库系统领域,并发控制机制主要有两种,即锁和多版本机制。

    1.事务在加锁时有多种方式:

    一次性锁协议

    事务开始时,即一次性申请所有的锁,之后不会再申请任何锁,如果其中某个锁不可用,则整个申请就不成功,事务就不会执行,在事务尾端,一次性释放所有的锁。一次性锁协议不会产生死锁的问题,但事务的并发度不高。

    两阶段锁协议

    整个事务分为两个阶段,前一个阶段为加锁,后一个阶段为解锁。在加锁阶段,事务只能加锁,也可以操作数据,但不能解锁,直到事务释放第一个锁,就进入解锁阶段,此过程中事务只能解锁,也可以操作数据,不能再加锁。两阶段锁协议使得事务具有较高的并发度,因为解锁不必发生在事务结尾。它的不足是没有解决死锁的问题,因为它在加锁阶段没有顺序要求。如两个事务分别申请了A, B锁,接着又申请对方的锁,此时进入死锁状态。

    树形协议

    假设数据项的集合满足一个偏序关系,访问数据项必须按此偏序关系的先后进行。如di->dj,则要想访问dj,必须先访问di。这种偏序关系导出一个有向无环图(DAG),因此称为树形协议。树形协议的规则有:
    树形协议只有独占锁;
    事务T第一次加锁可以对任何数据项进行;
    此后,事务T对数据项Q的加锁前提是持有Q的父亲数据项的锁;
    对数据项的解锁可以随时进行;
    数据项被事务T加锁并解锁之后,就不能再被事务T加锁。
    树形协议的优点是并发度好,因为可以较早地解锁。并且没有死锁,因为其加锁都是顺序进行的。
    缺点是对不需要访问的数据进行不必要的加锁。

    时间戳排序协议

    每个事务都有一个唯一的时间戳,也就是其进入系统的时间。时间戳有大小之分,如果事务Ti比Tj先进入系统,则TS(Ti)<TS(Tj)。对于每个数据项Q,有两个时间戳与其绑定:一个是W-TS(Q),表示最近一次写数据项Q的事务的时间戳;一个是R-TS(Q),表示最近一次读数据项Q的事务的时间戳。Thomas协议是对时间戳排序协议的改进,具体内容如下:
    若事务Ti发起一个write(Q),则
    如果TS(Ti)<R-TS(Q),则表明Ti准备写的值还没来得及写入,Q就提前被读取了,所以Ti的write(Q)操作被拒绝,并且事务Ti被回滚。
    如果TS(Ti)<W-TS(Q),表明Ti写的值已过期,比它更新的值已经写到Q上,所以Ti的write(Q)操作被拒绝。
    剩下的情况,write(Q)操作被允许。

    事务在加锁时存在粒度的区别

    如数据库锁,表锁,行锁,字段锁;页锁等。不同的数据库支持的锁粒度不同,BerkeleyDB支持页锁,即对数据项所在的内存页加锁。

    2.多版本机制:

    锁是针对集中式数据管理设计的,缺点是降低了事务的并发,并且锁本身有开销。在分布式系统,尤其是读多写少的系统中,采用多版本机制更合适。每个数据项都有多个副本,每个副本都有一个时间戳,根据多版本并发控制协议(MVCC)维护各个版本。

    MVCC又称为乐观锁,它在读取数据项时,不加锁;在更新数据项时,直到最后要提交时,才会加锁。这与CAS(Compare and Swap)的机制很类似,为了提高并发度,它更新数据前,会将数据拷贝一份,进行一系列修改,并且拷贝的同时,会记录当前的版本号(时间戳),当修改完毕,即将提交时,再检查此时的版本号是否与刚才记录的一致,如果不一致,则表明数据项被其他事务修改,当前事务的修改被取消。否则,正式提交修改,并增加版本号。
    与MVCC相对,基于锁的并发控制机制称为悲观锁,因为它认为其他事务修改自己正在使用的数据项的概率很高,因此对数据项加锁以阻塞其他事务的读和写。

    更多相关内容
  • 本小节介绍的两阶段封锁协议(2PL)是其中一种解决方式,它是一种悲观的解决策略,相应的,还有一类乐观的解决策略。 2. Lock Types 在索引并发控制那一小节提到过,Lock和Latch的区别。Latch指物理层面对数据...

    1. Overview

    前面一小节(并发控制理论)介绍了如何并发执行多个事务,设置检测机制判断执行调度满足可串行化。那些方法假设DBMS已知所有负载,然而,在真实系统中,系统往往并不知道用户在未来可能发送的所有请求,在这种情况下如何保证最终产生可串行化调度是一个新的问题。本小节介绍的两阶段封锁协议(2PL)是其中一种解决方式,它是一种悲观的解决策略,相应的,还有一类乐观的解决策略。

    2. Lock Types

    在索引并发控制那一小节提到过,Lock和Latch的区别。Latch指物理层面对数据结构的锁,Lock指对逻辑层面的事务、数据库对象的锁。

    锁的类型分为读锁和写锁,读锁之间不互斥,写锁与任意的锁都互斥。

    为了在事务并发过程中避免读写冲突,可以使用锁对对象进行管理,Lock Manager中记录当前锁的分配情况。

    下图是一个使用锁实现数据对象原子访问的例子,但仅仅这样这还不够,下面的例子不满足可串行化,出现了不可重复读的问题。

    两阶段封锁(2PL)是一种能够无需提前知道未来所有事务内容的情况下保证调度冲突可串行化的一种并发协议。

    两阶段封锁顾名思义分为两个阶段,分别是Growing阶段和Shrink阶段。在Growing阶段,事务从Lock Manager处获得执行事务所需要的所有数据对象的锁;随后进入Shrink阶段,只能释放Growing阶段获得的锁,不能够重新获取新的锁。

    Shrink阶段,只能释放Growing阶段获得的锁,不能够重新获取新的锁(避免了提到的脏读问题)。

    下面是一个运用2PL执行事务T1和事务T2的例子。

    到目前为止介绍的2PL还不够完美,还会发生级联中止的问题(cascading abort)。

    例如下图所示,若T1最终ABORT掉,由于T2已经读了T1写后的值,出现脏读问题,导致T2也要中止。若级联中止导致了DBMS事务冲突率较高,成功提交的事务变少影响性能,可以通过Strong Strict 2PL彻底避免。

    Strong Strict 2PL指只有等到事务最终执行完,决定COMMIT前再释放所有锁(这里一直有个疑问,就是会不会COMMIT失败?)。

    可以看出,Strong Strict 2PL可以彻底避免级联中止的问题,但这是一个trade-off的过程,使用Strong Strict 2PL的同时也降低了执行的并行度。

    下图是一个使用Strong Strict 2PL计算A+B的例子,T2直到T1决定COMMIT了才能够获得A的写锁。

    几种调度的关系如图所示。

    到目前为止介绍的2PL还可能发生死锁的问题,如下图所示,T1和T2因为互相争用锁而发生死锁。

    在发生事务死锁情况下,Wait For 图表现出是一个环。处理死锁的方式可以通过死锁检测或者提前预防死锁的发生。

    对于死锁的检测,Wait For 图可以判断调度中是否有死锁,与上一小节介绍的冲突依赖图不同的是,对于依赖图中冲突的两个事务,先执行的事务指向后发生的事务;Wait For 图中的有向边Ti->Tj表示事务Ti等待事务Tj释放锁。

    下图所示是一个死锁的例子。

    一旦检测到有死锁产生,DBMS会回滚部分事务打破死锁状态,从而能够让系统继续运行,被回滚的事务重新执行。

    允许根据不同规则来选择回滚的事务,目的还是想要回滚带来的损失最小,同时也要避免starvation(饥饿)问题。

    同时,被回滚的事务可以考虑只回滚事务中导致死锁的操作,剩余的操作不回滚,减少回滚带来的损失。

    也可以通过设置预防机制彻底避免死锁的发生,如下图所示的两种策略。第一种策略统一按照时间戳顺序发放锁,第二种相反,通过规定统一的锁分配策略来避免死锁的发生。

    下图分别两种机制对锁争用的处理。

    若一个查询涉及1000万行记录,lock manager同时管理1000万个锁将会造成较低的处理性能。

    通过层级化锁可以达到对大规模tuple上锁的目的。

    具体而言,这种锁叫Intention Lock。

    IS、IX、SIX互斥情况。

    下图是T1、T2、T3通过层次化锁实现并发执行的例子。

    这种层级化锁机制优化了需要获取大规模锁的查询性能,同时也考虑了查询的并发性。

    展开全文
  • 两阶段封锁协议

    千次阅读 2019-07-23 23:55:02
    锁协议是指每个事务的执行分为阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段)。 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁,在进行写操作之前要申请并获得X锁。...

    参考 https://segmentfault.com/a/1190000012513286

    定义

    两段锁协议是指每个事务的执行分为两个阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段)。
    加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁,在进行写操作之前要申请并获得X锁。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
    解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。
    两段封锁法可以这样来实现:事务开始后就处于加锁阶段,一直到执行ROLLBACK和COMMIT之前都是加锁阶段。ROLLBACK和COMMIT使事务进入解锁阶段,即在ROLLBACK和COMMIT模块中DBMS释放所有封锁 。

    简单来说就是解锁之后不能再加锁 。
    在这里插入图片描述
    加锁时机
    当对记录进行更新操作或者select for update(X锁)、lock in share mode(S锁)时,会对记录进行加锁。
    解锁时机
    commit或者rollback时。

    一个例子

    这道题来自牛客网,根据上面的解释,很显然T1是遵守两阶段封锁协议。在这里插入图片描述

    二段锁对性能的影响实例

    下面举个具体的例子,来讲述二段锁对应用性能的影响,我们举个库存扣减的例子:

    方案一:
    start transaction;
    // 锁定用户账户表
    select * from t_accout where acount_id=234 for update
    //生成订单
    insert into t_trans;
    // 减库存
    update t_inventory set num=num-3 where id=${id} and num>=3;
    commit;
    
    方案二:
    start transaction;
    // 减库存
    update t_inventory set num=num-3 where id=${id} and num>=3;
    // 锁定用户账户表
    select * from t_accout where acount_id=234 for update
    //生成订单
    insert into t_trans;
    commit;
    

    我们的应用通过JDBC操作数据库时,底层本质上还是走TCP进行通信,MySQL协议是一种停-等式协议(和http协议类似,每发送完一个分组就停止发送,等待对方的确认,在收到确认后再发送下一个分组),既然通过网络进行通信,就必然会有延迟,两种方案的网络通信时序图如下:

    在这里插入图片描述
    由于商品库存往往是最致命的热点,是整个服务的热点。如果采用第一种方案的话,TPS理论上可以提升3rt/rt=3倍。而这是在一个事务中只有3条SQL的情况,理论上多一条SQL就多一个rt时间。

    另外,当更新操作到达数据库的那个点,才算加锁成功。commit到达数据库的时候才算解锁成功。所以,更新操作的前半个rt和commit操作的后半个rt都不计算在整个锁库存的时间内。

    从上面的例子可以看出,在一个事务操作中,将对最热点记录的操作放到事务的最后面,这样可以显著地提高服务的吞吐量。

    select for update 和 update where的最优选择

    我们可以将一些简单的判断逻辑写到update操作的谓词里面,这样可以减少加锁的时间,如下:

    方案一:
    start transaction
    num = select count from t_inventory where id=234 for update
    if count >= 3:
        update t_inventory set num=num-3 where id=234
        commit 
    else:
        rollback
    
    方案二:
    start transaction:
        int affectedRows = update t_inventory set num=num-3 where id=234 and num>=3
        if affectedRows > 0:
            commit
        else:
            rollback
    

    延时图如下:
    在这里插入图片描述
    从上图可以看出,加了update谓词以后,一个事务少了1rt的锁记录时间(update谓词和select for update对记录加的都是X锁,所以效果是一样的)。

    展开全文
  • 数据库基础知识详解:乐观/悲观锁、封锁级别、三级封锁协议以及锁协议

    写在文章前:本系列文章用于博主自己归纳复习一些基础知识,同时也分享给可能需要的人,因为水平有限,肯定存在诸多不足以及技术性错误,请大佬们及时指正。

    4.乐观锁和悲观锁

    乐观锁和悲观锁在数据库和多线程并发中常被提及,但它们并不是某两个特定的锁,而是两个锁的宏观理念。

    • 悲观锁:认为数据随时会被修改,因此每次读取数据之前都会上锁,防止其它事务读取或修改数据。应用于数据更新比较频繁的场景。

    • 乐观锁:操作数据时不会上锁,但是更新时会判断在此期间有没有别的事务更新这个数据,若被更新过,则失败重试。适用于读多写少的场景。

    乐观锁的实现方式有:
    (1)加一个版本号或者时间戳字段,每次数据更新时同时更新这个字段。
    (2)先读取想要更新的字段或者所有字段,更新的时候比较一下,只有字段没有变化才进行更新。

    5.常见的封锁级别

    意向锁是 InnoDB (MySQL加的数据引擎)自动加的, 不需要用户干预。 对于UPDATE、DELETE和INSERT 语句, InnoDB 会自动给涉及数据集加排他锁(X)。对于普通SELECT 语句,InnoDB 不会加任何锁。事务可以通过以下语句显式给记录集加共享锁或排他锁: 共享锁(S):SELECT * FROM table_name WHERE … LOCK IN SHARE MODE。 其他 session 仍然可以查询记录,并也可以对该记录加 share mode 的共享锁。但是如果当前事务需要对该记录进行更新操作,则很有可能造成死锁。 排他锁(X):SELECT * FROM table_name WHERE … FOR UPDATE。其他 session 可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁。

    排它锁(Exclusive Lock)/ X锁:事务对数据加上X锁时,只允许此事务读取和修改此数据,并且其它事务不能对该数据加任何锁。

    共享锁(Shared Lock)/ S锁:加了S锁后,该事务只能对数据进行读取而不能修改,并且其它事务只能加S锁,不能加X锁。

    意向锁(Intention Locks):一个事务在获得某个数据行对象的 S 锁之前,必须先获得整个表的 IS 锁或更强的锁。一个事务在获得某个数据行对象的 X 锁之前,必须先获得整个表的 IX 锁。IS/IX 锁之间都是兼容的。

    好处:如果一个事务想要对整个表加X锁,就需要先检测是否有其它事务对该表或者该表中的某一行加了锁,这种检测非常耗时。有了意向锁之后,只需要检测整个表是否存在IX/IS/X/S锁就行了锁的作用:用于管理对共享资源的并发访问,保证数据库的完整性和一致性。

    封锁粒度

    MySQL 中提供了两种封锁粒度:行级锁以及表级锁

    简单来说即锁住整张表或者锁住一行的数据。

    封锁粒度小封锁粒度大
    优点锁定的数据量较少,发生锁竞争的可能较小,系统的并发性更好。系统开销较小。(加锁、释放锁、检查锁的状态都需要消耗资源)。
    缺点系统开销较大大。锁定的数据量较多,发生锁竞争的可能较大,系统的并发性较差。

    6.三级封锁协议

    • 一级封锁协议:事务在修改数据之前必须先对其加X锁,直到事务结束才释放。

      可以解决丢失修改问题(两个事务不能同时对一个数据加X锁,避免了修改被覆盖)

    • 二级封锁协议:在一级的基础上,事务在读取数据之前必须先加S锁,读完后释放。

      可以解决脏读问题(如果已经有事务在修改数据,就意味着已经加了X锁,此时想要读取数据的事务并不能加S锁,也就无法进行读取,避免了读取脏数据)

    • 三级封锁协议:在二级的基础上,事务在读取数据之前必须先加S锁,直到事务结束才能释放。

      可以解决不可重复读问题(避免了在事务结束前其它事务对数据加X锁进行修改,保证了事务期间数据不会被其它事务更新)。

    7.两段锁协议

    什么是两段锁协议?

    定义:事务必须严格分为两个阶段对数据进行加锁和解锁的操作,第一阶段加锁,第二阶段解锁。

    也就是说一个事务中一旦释放了锁,就不能再申请新锁了。

    可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。

    事务遵循两段锁协议是保证可串行化调度的充分条件(注意不是充要条件,而是充分条件。即事务遵循两段锁协议一定能保证可串行化调度,但保证可串行化调度不一定需要遵循两段锁协议)。

    展开全文
  • Mysql的两阶段锁协议

    千次阅读 2022-01-30 21:58:46
    mysql的事务为什么需要两阶段锁协议两阶段锁协议是什么?在mysql优化中如何利用两阶段锁的特性提交mysql并发量?
  • MySql-两阶段加锁协议

    2021-01-20 01:11:12
    MySql-两阶段加锁协议前言此篇博客主要是讲述MySql(仅限innodb)的两阶段加锁(2PL)协议,而非两阶段提交(2PC)协议,区别如下:2PL,两阶段加锁协议:主要用于单机事务中的一致性与隔离性。2PC,两阶段提交协议:主要用于...
  • 前言本文主要是讲述MySql(仅限innodb)的两阶段加锁(2PL)协议,而非两阶段提交(2PC)协议,区别如下:2PL,两阶段加锁协议:主要用于单机事务中的一致性与隔离性。2PC,两阶段提交协议:主要用于分布式事务。MySql本身针对...
  • 所谓锁协议是指所有事务必须分阶段对数据项加锁和解锁。 .在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁 .在释放一个封锁之后,事务不再申请和获得任何其他封锁。所谓"段"锁的含义是...
  • 锁协议

    千次阅读 2017-11-17 10:19:55
    1、锁协议是指所有事务必须分阶段对数据项加锁和解锁:  1.1、在对任何数据进行读、写操作之前,要申请并获得对该数据的封锁。  1.2、 每个事务中,所有的封锁请求先于所有的解锁请求。  ...
  • 两阶段提交协议 定义 : 在计算机网络以及数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的算法 情景 在分布式系统中,每个节点虽然可以知道自己的操作是否成功,却无法知道...
  • 展开全部区别如下:1、过程不同三级封锁协议是一部完成封锁的,而后者却要62616964757a686964616fe78988e69d8331333431356566分为阶段,耗费时间2、含义不同锁协议是指每个事务的执行可以分为阶段:生长...
  • 协议具有多版本并发控制机制与两阶段封锁机制的优点,使用如下策略以减少延误截止时间事务数量:若冲突集中有比持事务Ti优先级高的事务,且Ti重启动不会延误截止时间,则Ti重启动,冲突集中优先级最高的事务获得;...
  • 三级封锁协议用于解决修改丢失、不可重复读和读脏数据问题,解决问题的焦点是给数据库对象何时加锁、什么样的 一级封锁协议:事务T在修改数据R之前必须对其X,解决修改丢失问题 二级封锁协议:在一级封锁...
  • (mysql采用两阶段封锁协议) 调度是一组事务的操作的某种合并结果。(mysql支持多事务并行执行) 一个调度是合法的,如果同一时间没发生个不同事务的冲突。(mysql需要保证并行事务不冲突) 因为每个事务T都是...
  • 分析了当提交状态参与者允许执行状态的参与者访问其数据时,由数据冲突访问而引起的各种依赖关系,提出了一种基于两阶段封锁的乐观提交协议(OCP)。让参与者先发送一个WORK-STARTED消息来代替WORKDONE消息,考虑依赖关系...
  • 参考以下文章:https://blog.csdn.net/weixin_38118016/article/details/90271468
  • 基本的封锁类型有种:排它(X)和共享(S).所谓X,是事务T对数据A加上X时,只允许事务T读取和修改数据A,...所谓S,是事务T对数据A加上S时,其他事务只能再对数据AS,而不能X,直到T释放A上的S。若...
  • 两阶段锁协议的理解
  • 锁协议 封锁的粒度 多粒度封锁 意向锁 锁的强度   前提 并发控制技术与前一篇提到的数据库恢复技术是主要的事务处理技术,同时并发控制机制和数据库恢复机制是数据库管理系统(DBMS)的重要组成部分。 ...
  • 一、前言 在单个数据库实例时候,我们可以在一个数据源的事务(本地事务)内做多步数据库操作,在事务内的多个操作要么全部执行生效,...二、二阶段协议 单个数据库实例内的事务我们称为本地事务,需要保证多个...
  • #MySql-两阶段加锁协议 ##前言此篇博客主要是讲述MySql(仅限innodb)的两阶段加锁(2PL)协议,而非两阶段提交(2PC)协议,区别如下:2PL,两阶段加锁协议:主要用于单机事务中的一致性与隔离性。2PC,两阶段提交协议:主要用于...
  • MySql-两阶段加锁协议前言此篇博客主要是讲述MySql(仅限innodb)的两阶段加锁(2PL)协议,而非两阶段提交(2PC)协议,区别如下:2PL,两阶段加锁协议:主要用于单机事务中的一致性与隔离性。2PC,两阶段提交协议:主要用于...
  • (1)改写T和T2, 增加加锁操作和解锁操作,并要求遵循两阶段封锁协议。 (2)说明T和T2的执行是否会引起死锁,给出T和T2的一个调度并说明之。 二、问题解答 (1)如下表所示 T1 T2 Slock A R(A) Slock B ...
  • mysql中的锁协议和三级封锁协议

    千次阅读 2019-04-17 09:14:42
    锁协议 一个事务中一旦开始释放锁,就不能再申请新锁了。事务的加锁和解锁严格分为阶段,第一阶段加锁,第二阶段解锁。 目的 :”引入2PL是为了保证事务的隔离性,保证并发调度的准确性,多个事务在并发的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,984
精华内容 15,193
关键字:

两阶段封锁协议