精华内容
下载资源
问答
  • 两段锁协议

    千次阅读 2017-07-14 15:15:28
    可以证明,若并发执行的所有事务均遵守两段锁协议,则对这些事务的任何并发调度策略都是可 串行化 的。 最后,说一下什么是 可串行化 :多个事务的并发执行是正确的,当且仅当其结果与某一次序串行地执行它们时的...

    我们都知道,事务调度一般有串行调度和并行调度,那首先来了解几个概念。

    并发控制:所谓并发控制,是指多用户共享的系统中,许多用户可能同时对同一数据进行操作。

    调度:指的是事务的执行次序。

    串行调度:多个事务依次串行执行,且只有当一个事务的所有操作都执行完后才执行另一个事务的所有操作。只要是串行调度,执行的结果都是正确的。

    并行调度:利用分时的方法同时处理多个事务。但是并行调度的调度结果可能是错误的,可能产生不一致的状态,包括有:丢失修改,不可重复读和读脏数据。

    其实比较明显的是虽然串行调度能够保证调度结果的正确性,但是却限制了系统并行性的发挥,不能有效利用资源,但是并行调度的调度结果又可能出现错误,而且可能不具有串行,正是因为这样,有一个具有串行调度效果的并行调度方法,而两段锁协议就是保证并行事务可串化的方法。

    两段锁协议:是指所有的事务必须分两个阶段对数据项加锁和解锁。即事务分两个阶段,第一个阶段是获得封锁。事务可以获得任何数据项上的任何类型的锁,但是不能释放;第二阶段是释放封锁,事务可以释放任何数据项上的任何类型的锁,但不能申请。

    第一阶段是获得封锁的阶段,称为扩展阶段:其实也就是该阶段可以进入加锁操作,在对任何数据进行读操作之前要申请获得S锁,在进行写操作之前要申请并获得X锁,加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。就是加锁后就不能解锁了。

    第二阶段是释放封锁的阶段,称为收缩阶段:当事务释放一个封锁后,事务进入封锁阶段,在该阶段只能进行解锁而不能再进行加锁操作。

    这里举个例子说明:

    事务T1遵守两段锁协议,其封锁序列是:
    Lock A, Read A, A:=A+100, Write A, Lock B, Unlock A, Read B, Unlock B, Commit;
    可以证明,若并发执行的所有事务均遵守两段锁协议,则对这些事务的任何并发调度策略都是可 串行化的。
    最后,说一下什么是 可串行化:多个事务的并发执行是正确的,当且仅当其结果与某一次序串行地执行它们时的结果相同,称这种调度策略是可串行化调度。

    展开全文
  • 两段锁协议 封锁的粒度 多粒度封锁 意向锁 锁的强度   前提 并发控制技术与前一篇提到的数据库恢复技术是主要的事务处理技术,同时并发控制机制和数据库恢复机制是数据库管理系统(DBMS)的重要组成部分。 ...

    主要内容

    两种基本封锁类型 

    封锁协议

    活锁

    死锁

    多粒度封锁

    意向锁

    锁的强度


     

    前提

    并发控制技术与前一篇提到的数据库恢复技术是主要的事务处理技术,同时并发控制机制和数据库恢复机制是数据库管理系统(DBMS)的重要组成部分。

    单处理机系统中,事务的并行执行实际上是这些并行事务轮流交叉运行。这种并行执行方式称为交叉并发方式(interleaved concurrency)。虽然单处理机系统中的并行事务并没有真正地(物理上)并行运行,但是减少了处理机和各设备的空闲时间,提高了系统的效率。

    多处理机系统中,当事务数小于处理机数时,每个处理机可以运行一个事务,实现真正意义上的并行运行。这种并行执行方式称为同时并发方式(simultaneous concurrency)

    当多个用户并发地操作数据库时,就有可能出现多个事务同时存取同一数据的情况,这种情况可能会破坏事务的一致性和数据库的一致性,所以数据库管理系统(DBMS)必须提供并发控制机制。并发控制机制是衡量一个DBMS性能的重要标志之一。


     

    并发操作带来的数据不一致性

    以下三类数据不一致性的主要原因是并发操作破坏了事务的隔离性

    1)丢失修改(lost update):

    事务T1和T2先后读入同一数据并修改,T1先提交,T2后提交,T2提交的结果将覆盖T1的结果,导致T1的修改被丢失。

    2)不可重复读(non-repeatable read):

    事务T1读入某一数据后(未进行操作),T2对同一数据进行了操作(修改、插入、删除),当T1再次读入该数据时,得到与前一次不同的值(或者多了、少了某些记录)。这种不一致性与丢失修改的理想情况相反。

    3)读“脏”数据(dirty read):

    事务T1修改某一数据后将其写入磁盘,事务T2读入修改后的数据,此时T1由于某种原因被撤销(ROLLBACK),被T1修改的数据恢复原值,导致T2读入的数据与数据库中的数据不一致。


     

    封锁

    事务T在对某个数据对象,如表、记录等操作之前,需要先向系统发出加锁请求,在事务T释放它的锁之前,其他事务不能对此数据进行修改。

     

    两种基本封锁类型 

    1)排他锁(exclusive locks,X锁):

    排他锁又称为写锁。事务T对数据对象A加上X锁后,只允许事务T对A进行读取和修改,其他事务不能对A加任何类型的锁,直到T释放它的X锁为止。从而保证了其他事务在T释放A上的X锁之前不能对A进行读取和修改。

    2)共享锁(share locks,S锁):

    共享锁又称为读锁。事务T对数据对象A加上S锁后,事务T只能对A进行读取,而不能修改。其他事务可以继续对A加上S锁,但是不能加X锁,直到T释放它的S锁为止。从而保证了其他事务可以读取A,但是在T释放A上的S锁之前不能对A进行修改。

    *需要注意的是,同一事务可以不断对某个数据对象加锁,不需要等锁的释放。

     

    封锁协议

    1)一级封锁协议:

    定义:事务T在修改数据A前,必须先对A加X锁,直到事务结束才释放因此X锁又被称为写锁,意为修改。

    目的:解决“丢失修改”的不一致问题,即在下一个事务操作前,先把上一个事务的修改操作结束。

    实现:事务T1的X锁→事务T2的X锁

    事务T1对数据对象A加上X锁后,只有等事务T1(修改)结束,释放X锁,事务T2才能对A加锁并进行操作(读取、修改)。

     

    2)二级封锁协议:

    定义:在一级封锁协议的基础上,增加事务T在读取数据A前,必须先对A加S锁,读完后即可释放因此S锁又被称为读锁,意为读取。

    目的:在一级封锁协议的基础上,进一步解决“读‘脏’数据”的不一致问题,即在下一个事务读取前,先等上一个事务的撤销操作结束。

    实现:事务T1的X锁→事务T2的S锁(读取数据后释放S锁)

    事务T1对数据对象A加上X锁后,只有等事务T1(修改、撤销)结束,释放X锁,事务T2才能对A加锁并进行操作(读取)。

     

    3)三级封锁协议:

    定义:在一级封锁协议的基础上,增加事务T在读取数据A前,必须先对A加S锁,直到事务结束才释放(与二级的区别)

    目的:在二级封锁协议的基础上,进一步解决“不可重复读”的不一致问题,即在下一个事务修改前,先等上一个事务的重复读操作结束。

    实现:事务T1的S锁(事务结束后释放S锁)→事务T2的X锁

    事务T1对数据对象A加上S锁后,只有等事务T1(重复读取)结束,释放S锁,事务T2才能对A加X锁并进行操作(修改)。


     

    活锁和死锁

    和操作系统一样,封锁的方法可能引起活锁和死锁等问题。

     

    活锁

    根据事务的优先级顺序,可能会出现某个事务永远在等待封锁的情况,即事务T1封锁了数据对象A后,T2、T3陆续请求封锁,但是T1释放锁后,系统优先批准了T3的请求,T2仍然在等待。

    最简单的解决方法就是先来先服务(FCFS),不考虑事务的优先级。

     

    死锁

    事务T1封锁了数据A,事务T2封锁了数据B,然后T1请求封锁B,与此同时T2也请求封锁A,但因为两个事务的请求都需要等待对方释放锁,这样就出现了永远在等待对方的死锁。

    在数据库中,解决死锁问题主要有两类方法:预防和诊断解除。

    1)预防:

    1. 一次封锁法:每个事务一次将所有要使用的数据加锁,否则事务不能继续执行。

    带来的问题:阻碍了其他事务对数据的利用,从而降低了系统的并发度。

    2. 顺序封锁法:预先对数据规定一个封锁顺序,所有事务都按照这个顺序加锁,保证“先到先得”。

    带来的问题:需要处理的信息太多,开销大,成本高。

     

    2)诊断与解除:

    1. 超时法:某个事务的等待时间超过规定时间,则系统判定为死锁。

    带来的问题:规定时间过短,可能误判死锁;规定时间过长,可能不能及时发现死锁。

    2. 等待图法:并发控制子系统周期性地生成事务等待图,动态地反映所有事务的等待情况。如果发现图中存在回路,则表示系统中出现了死锁。

    解除方法:通常撤销一个处理代价最小的事务,释放此事务持有的所有锁,使其他事务得以继续运行下去。


     

    并发调度的可串行性

    可串行性是并发事务正确调度的准则。

    当且仅当多个事务的并发执行结果,与按某一次序的串行执行结果相同,这种并发调度策略才是可串行化调度,即具有可串行性。

     

    例子(《数据库系统概论(第5版)》p318):

    事务T1:读B;A=B+1;写A

    事务T2:读A;B=A+1;写B

     

    那么如何判断可串行化调度呢?

    我们需要引入一个概念——冲突操作,冲突操作是指不同事务对同一个数据读写写写操作,其他操作都属于不冲突操作。

    很容易理解,对于同一数据的操作,不可能一边在读,同时另一边在写,更不可能两边都在写,这是不符合逻辑的。

     

    在一个调度策略中,交换两个事务的不冲突操作的次序,得到另一个调度策略,如果另一个调度策略的执行结果与原来的调度相同,则称原来的调度为冲突可串行化调度

    冲突可串行化调度是可串行化调度的充分条件,但不是必要条件。


     

    两段锁协议

    为了保证并发调度的正确性,DBMS的并发控制机制必须提供一定的手段来保证调度是可串行化的。

    目前DBMS普遍采用两段锁协议(TwoPhase Locking,2PL)来实现,所有事务遵守两段锁协议是可串行化调度的充分条件,但不是必要条件。

     

    两段锁的含义:

    1)第一阶段(扩展阶段):所有事务对数据加锁,但不能解锁;

    2)第二阶段(收缩阶段):所有事务对数据解锁,但不能加锁。

    *需要注意的是,不同事务对同一数据的加锁仍遵循两种锁的特性以及封锁协议。

     

    预防死锁的一次封锁法遵守两段锁协议;但是两段锁协议并不要求事务必须一次将所有要使用的数据全部加锁,因此遵守两段锁协议的事务可能发生死锁。


     

    封锁的粒度

    封锁粒度(granularity)是指封锁对象的大小。

    封锁对象可以是逻辑单元,也可以是物理单元。以关系数据库为例,逻辑单元包括属性值、属性值的集合、元组、关系、索引项、索引表乃至整个数据库;物理单元包括页(数据页或索引页)、物理记录等。

     

    封锁粒度与系统的并发度并发控制的开销有关:封锁粒度越大,数据库能封锁的数据单元越少,并发度越小,系统开销也变小。

    一般来说,处理个别元组的事务以元组为封锁粒度;处理某个关系的大量元组的事务以关系为封锁粒度;处理多个关系的大量元组的事务以数据库为封锁粒度。

     

    多粒度封锁

    在一个系统中,提供多种封锁粒度给不同的事务选择,这种封锁方法称为多粒度封锁( multiple granularity locking)

    • 定义多粒度树:多粒度树的根结点是整个数据库,表示最大的封锁粒度,叶结点是最小的封锁粒度,如元组、属性值等。
    • 封锁协议:给一个结点加锁的同时,该结点的所有后裔结点也会被加上同样的锁。对于该结点来说,这种加锁方式为显式封锁,而对于其后裔结点来说,这样的方式为隐式封锁

    在多粒度封锁中,显式封锁和隐式封锁的效果是一样的,因此系统检查封锁冲突时,不仅要检查显式封锁,还要沿着多粒度树上下检查隐式封锁。

    显然,这样的检查方法效率很低。为此人们引进了一种新型锁,称为意向锁(intention lock)

     

     

    意向锁

    对任何一个结点加锁时,必须先对它的上层结点加意向锁。

     

    三种常用的意向锁:

    1)意向共享锁(IS锁):

    对一个数据对象加IS锁,表示它的后裔结点拟(意向)加S锁

    事务T1对数据对象A加上IS锁后,事务T2可以继续加除X锁以外的锁。

    2)意向排他锁(IX锁):

    对一个数据对象加IX锁,表示它的后裔结点拟(意向)加X锁

    事务T1对数据对象A加上IX锁后,事务T2只能继续加IS或IX锁

    3)共享意向排他锁(SIX = S+IX锁):

    对一个数据对象先加S锁,再加IX锁。例如对某个表加SIX锁,则表示该事务要读(S)整个表,同时会更新(IX

    )个别元组。

    事务T1对数据对象A加上SIX锁后,事务T2只能加IS锁

     

    在具有意向锁的多粒度封锁方法中,任意事务T要对一个数据对象加锁,必须先对它的上层结点加意向锁。

    申请封锁时应该按自上而下的次序进行,释放封锁时则应该按自下而上的次序进行。(栈结构)

     

    具有意向锁的多粒度封锁方法提高了系统的并发度,减少了加锁和解锁的开销,已经在实际的DBMS产品中得到广泛使用。

     

    锁的强度

    锁的强度是指它对其他锁的排斥程度。

    一个事务在申请封锁时,以强锁代替弱锁是安全的,反之不然。

    强度排序:

    X > SIX > S / IX > IS

     

    展开全文
  • 行锁 MySQL的行锁都是在引擎层实现的,但是 MyISAM 不支持...行锁就是针对数据库中表的行记录的,这很好理解,比如事务 A 更新了一行,而这时候,事务 B 也要更新一行,则必须等事务 A 的操作完成后才能更新。...

    行锁

    MySQL的行锁都是在引擎层实现的,但是 MyISAM 不支持行锁,意味着并发控制只能使用表锁,同一张表任何时刻只能被一个更新在执行,影响到业务并发度。InnoDB 是支持行锁的,这也是 MyISAM 被 InnoDB 替换的重要原因之一。

    行锁就是针对数据库中表的行记录的锁,这很好理解,比如事务 A 更新了一行,而这时候,事务 B 也要更新一行,则必须等事务 A 的操作完成后才能更新。

    两阶段锁

    先举个例子,假设有一个表 t,主键是 id,其中一个字段是 k,在下面的操作中,事务 B 的 update 语句执行时,会是什么现象呢 ?说明:红色表示事务 A,黄色表示事务 B:

                                   

    这个问题的结论取决于事务 A 执行完前两条语句后,持有哪些锁,以及在什么时候释放。

    实际上,事务 A 持有两个记录的行锁,都是在 commit 的时候才释放的,所以事务 B 的 update 就会被阻塞,直到事务 A 执行 commit 之后,事务 B 才能被继续执行。也就是说,在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,需要等事务结束时才释放,这就是两阶段锁协议,分为加锁阶段和解锁阶段,所有的 lock 操作都在 unlock 操作之后。

    假设你负责实现一个电影票在线交易业务,顾客 userA 要在影院 cinema 购买电影票,需要涉及以下操作:

    1. 扣除顾客 userA 账户余额

    2. 增加影院 cinema 账户余额

    3. 记录一条交易日志

    也就是说,完成这次交易,需要 update 两条记录,并 insert 一条记录。当然为了保证交易的原子性,我们需要这三个操作放在一个事务中。与此同时,还有顾客 userB 也在影院购买电影票,那么你会怎样安排这三个语句在事务中的顺序呢?

    首先发现冲突的部分是语句 2,就是两个事务都要给 cinema 的账户余额增加电影票价。根据两阶段协议,不论怎么安排语句,所有的操作需要的行锁都是在事务提交的时候才释放的,要想使行锁在事务中不会停留太长时间,最大程度的减少了事务之间的锁等待,应该把语句 2 放在最后面。如下图所示:

                                

    死锁

    如下图所示,事务 A 在等待事务 B 释放 id = 2 的行锁,而事务 B 在等待 事务 A 释放 id = 1 的行锁,事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态。

                               

    在并发系统中,不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程进入无限等待的状态,成为死锁。

    当进入死锁状态时,有下列 2 种策略:

    1. 通过 innodb_lock_wait_timeout 来设置超时时间,InnoDB 中默认值是 50s,第一个被锁住的事务 A 等待超过 50s 才会超时退出,其他事务才能得以执行,对于在线服务来说,这个等待时间往往是无法接受的。如果设置太短 1s,可能有的事务只是简单的锁等待,就被退出了,会出现很多误伤。

    2. 通过设置 innodb_deadlock_detect = on,发起死锁检测,发现死锁之后主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。比如回滚事务 A,让事务 B 继续执行。

    死锁检测

    正常情况下使用第 2 种策略的,但是快速发现死锁并进行处理,也是有额外负担的。你可以想象一下这个发现死锁的过程:每当一个事务被锁的时候,就要看看他依赖的线程有没有被别人锁住,判断是否出现了循环等待,也就是死锁。

    假设有 1000 个并发线程,都要同时更新同一行,第 1 个线程来的时候检测数是 0;第 2 个线程来的时候,需要检测【线程1】有没有被别人锁住;第 3 个线程来的时候,需要检测【线程1,线程2】有没有被其他线程锁住,以此类推,第 n 个线程来的时候,检测数是 n - 1,所以总的检测数是 0 + 1 + 2 + 3 + 。。。+ (n - 1) = n(n -1)/2,所以时间复杂度应该是 O(n²)。

    也就是 1000 个并发线程同时操作同一行,那么死锁检测操作就是 100 万这个量级的,虽然最终检测的结果是没有死锁,但是这期间要消耗大量的 CPU 资源,就会看到 CPU 利用率很高,但是每秒却执行不了几个事务。

    那么怎么处理这种热点行更新导致的性能问题呢?

    1. 如果你能确定这个业务一定不会出现死锁,可以临时把死锁关掉,这种操作带有一定风险,因为业务设计的时候一般不会把死锁当成一个严重错误,毕竟出现死锁了,就回滚,然后通过业务重试一般就没有问题了,这是业务无损的,而关掉死锁检测意味着可能出现大量超时,这是业务有损的。

    2. 控制并发度,比如同一行最多只有 10 个线程在更新,这样死锁检测的成本很低,一个直接的想法就是在客户端做并发控制。可是如果客户端有 600 个,即使每个客户端控制到只有 5 个线程,汇总到数据库服务端以后,峰值并发数也有可能达到 3000。因此这个并发控制要在服务端,比如引入中间件来实现,在进入引擎之前排队。

    3. 将一行改成逻辑上的多行来处理,比如影院的账户余额等于 10 行记录的值总和,这样每次给影院账户加金额的时候,随机选取其中一条记录来加,冲突概率变为原来的1/10,减少锁的等待个数,也就减少了死锁检测的 CPU 消耗。这个方案看上去是无损的,但是需要根据业务逻辑做详细设计。如果账户余额减少,比如退票,这个时候就要考虑当一部分行记录变为 0 的时候,代码要有特殊处理。

    展开全文
  • 所以只要是使用一次封锁法的协议都遵循两段锁协议,同时也说明两段锁协议也有死锁问题。 关于死锁这里提一嘴,有两种方法解决: 一是预防:一次封锁法、顺序封锁法; 二是解决:超时法、等待图法。 其中等待图法指的...

    一、并发调度


    并发调度啥意思?

    就是当很多事务同时执行的时候应该按照什么顺序执行,应该按照排队的顺序执行,这就是 串行调度

    串行执行肯定是正确的,但是改变一下位置有影响吗?

    这就要看改变顺序之后执行的结果是否和不改变顺序执行的结果一致了。

    如果改变顺序之后执行的结果和串行调度的执行结果一致,那么就说这种调度是 可串行化调度

    可串行性是并发事务正确调度的准则。

    比如:

    事务 T1: 读 B A=B+1;写回 A;
    事务 T2: 读 A B=A+1;写回 B;
    

    假设 A、B 的初始值都是 2,串行调度指的就是先执行 T1 再执行 T2,或者先执行 T2 再执行 T1,这是没有区别的,都是正确的。

    1、先执行 T1:结果是 A=3,B=4;
    2、先执行 T2:结果是 B=3,A=4;
    

    其实这里执行的顺序可以是(R代表读,W代表写),这两个都是 串行调度

    1、R1(B)  W1(A)  R2(A)  W2(B)
    2、R2(A)  W2(B)  R1(B)  W1(A)
    

    我们只需要保证对同一数据对象的 读写(写读)操作写写操作 的相对位置不变即可。

    涉及对同一数据对象的读写操作称为 冲突操作

    解释一下前面的意思,这里的同一数据对象假设是 A ,W1(A) R2(A) 就是对同一数据对象的读写操作,那么他们的顺序是不能调换的,不然数据的结果就会改变。这里的顺序是先 写A 再读 A ,相对位置指的是他们中间可以有其他的操作。

    比如,在上一个例子中,如果执行的顺序改成下面的样子:

    R1(B)  R2(A)  W1(A)  W2(B)
    

    这就不对了,因为改变了关于数据对象 A 的读写顺序,应该是先写再读,因为这两个是冲突操作,所以不能随便调换位置,现在调换了无论如何也不能通过 交换不冲突操作的位置 变成那两个串行调度中的任何一个了。

    总之:不管是同一个事务还是多个事务操作,只要是涉及对同一数据对象的 读写操作写写操作 调换顺序的时候就要谨慎一点,不要改变了原来的结果。

    除了冲突操作之外的操作称为不冲突操作,如果一个调度通过 交换不冲突操作 的次序得到的另一个调度是串行的,那么称这个调度为 冲突可串行化 的调度。

    冲突可串行化调度只是可串行化调度的一种。有的时候就算改变了位置结果也不变。

    二、两段锁协议


    两段锁协议是为了保证事务并发调度的正确性,简称 2PL 协议。

    • 第一阶段是获得锁:扩展阶段:只允许加锁;
    • 第二阶段是释放封锁:收缩阶段:只允许解锁;

    如果并发执行的所有事务都遵循两段锁协议,那么对这些事务的任何并发调度都是可串行化的。

    可能大家回想到预防死锁时使用的 一次封锁法 。他们的区别在于两段锁协议只是说加锁的时候在一个阶段完成,没说要用的所有数据都必须加锁,而后者则要求所有使用到的数据必须加锁而且是在刚开始的加锁时期;所以只要是使用一次封锁法的协议都遵循两段锁协议,同时也说明两段锁协议也有死锁问题。

    关于死锁这里提一嘴,有两种方法解决:

    • 一是预防:一次封锁法、顺序封锁法;
    • 二是解决:超时法、等待图法。

    其中等待图法指的是有一个 有向图 ,每个 节点 表示正在执行的事务,每个 表示事务等待的情况,如果图中存在环路则说明出现了死锁。一般是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,使其他事务继续运行下去。

    另外对于封锁对象的大小不同,比如封锁一个元组,一张表或者整个数据库,分为不同的封锁粒度;这个时候就要分粒度封锁,在分粒度封锁的基础之上又发明了一种方法叫做意向锁

    那么这个意向锁又是个什么东西呢?

    意向锁建立在一个多粒度树上面,多粒度树就是将整个数据库按照对象的大小建立一棵树;

    这个时候你在一个节点上面加上一个意向锁,那么它以及他的子节点默认被加锁;

    具有意向锁的多粒度封锁方法提高了系统的并发度,减少了加锁和解锁的开销。

    展开全文
  • ZooKeeper分布式实现java例子,附完整可运行源代码

    万次阅读 多人点赞 2018-11-06 14:27:44
    本原创入门教程,涵盖ZooKeeper核心内容,通过实例和大量图表,结合实战,帮助学习者... ZooKeeper框架Curator分布式实现及源代码分析 zookeeper 开发实战(java客户端) ------------------------------------...
  • 阶段提交协议(two phase commit protocol,2PC)可以保证数据的强一致性,许多分布式关系型数据管理系统采用此协议来完成分布式事务。它是协调所有分布式原子事务参与者,并决定提交或取消(回滚)的分布式算法。...
  • 阶段封锁协议

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

    千次阅读 多人点赞 2017-08-07 18:13:05
    此篇博客主要是讲述MySql(仅限innodb)的阶段加锁(2PL)协议,而非阶段提交(2PC)协议,区别如下: 2PL,阶段加锁协议:主要用于单机事务中的一致性与隔离性。 2PC,阶段提交协议:主要用于分布式事务。 MySql...
  • 这是因为单线程下个方案的的粒度是一样的,而@TPCTransactional目前实现还比较简单,@TPCTransactional的代码比@Transactional少很多很多,所以性能还快一点。但在并发下,的粒度成了影响性能的关键,这时...
  • 在某些场景中,多个进程必须以互斥的方式独占共享资源,这时用分布式是最直接有效的。 随着技术快速发展,数据规模增大,分布式系统越来越普及,一个应用往往会部署在多台机器上(多节点),在有些场景中,为了...
  • 文章目录1、概述2、行级2.1 共享和排他2.2 意向共享和意向排他2.3 间隙(Next-Key)2.4 举例2.5 死锁和死锁检测3、表级3.1 表锁3.2 元数据(meta data lock,MDL)4、全局5、面试题5.1 全局相关...
  • 的状态总共有四种:无锁状态、偏向、轻量级和重量级。随着的竞争,可以从偏向升级到轻量级,再升级的重量级(但是的升级是单向的,也就是说只能从低到高升级,不会出现的降级)
  • Java消除和粗化

    万次阅读 多人点赞 2018-06-02 12:29:49
    转载自:Java消除非商业转载,可联系本人删除概述消除是Java虚拟机在JIT编译是,通过对运行上下文的扫描,去除不可能存在共享资源竞争的,通过消除,可以节省毫无意义的请求时间。实验看如下代码:package...
  • 让我们以互联网中常用的交易业务为例子: 上图中包含了库存和订单个独立的微服务,每个微服务维护了自己的数据库。在交易系统的业务逻辑中,一个商品在下单之前需要先调用库存服务,进行扣除库存,再调用...
  • 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚的概念。最近也是遇到一些问题,不搞清楚的概念,很容易碰壁,甚至有些时候自己连用没用对都不知道...
  • 【mysql】基于mysql数据库的分布式

    万次阅读 多人点赞 2018-11-07 15:45:48
    前言:在前面的zk和redis篇已经多次介绍什么是分布式,这里就不再赘述了,分布式常见的实现方式主要由三种,一种是基于zookeeper实现,一种是基于redis实现,今天要介绍的就是用的最少,最简单,但不太推荐使用的基于...
  • Java并发编程:自己动手写一把可重入

    千次阅读 多人点赞 2018-11-08 02:51:18
    线程不安全例子 public class Sequence { private int value; public void increament(int number) { int newValue = value + number; try { Thread.sleep((long) (Math.random() *...
  • 分布式简单入门以及三种实现方式介绍

    万次阅读 多人点赞 2018-01-11 21:16:28
    很多小伙伴在学习Java的时候,总是感觉Java多线程在实际的业务中很少使用,以...学过Java多线程的应该都知道什么是,没学过的也不用担心,Java中的可以简单的理解为多线程情况下访问临界资源的一种线程同步机制。
  • 并发控制中的乐观与悲观

    万次阅读 2015-08-23 16:27:30
    为什么需要(并发控制)?在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突。这就是著名的并发性问题。典型的冲突有: (1)丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是...
  • java 偏向

    千次阅读 2016-05-08 19:05:57
    java 偏向  Java偏向(Biased Locking)是Java6引入的一项多线程优化。它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。 偏向,顾名思义,它会偏向于第一个访问的线程,如果在接下来的...
  •  既然有了阶段协议的存在,那么如果事务中需要多个行,要把最可能造成冲突、最可能影响并发度的尽量往后放,这样可以在一定程度上减少死锁出现的概率。 死锁:  当并发系统中不同线程出现循环资源...
  • mysql能在并发情况下的mysql进行更好的优化 MySQL有三种的级别:页级、表级、行级,这3种的特性可大致归纳如下:  表级:开销小,加锁快;不会出现死锁;锁定粒度大,发生冲突的概率最高,并发度最低...
  • 深入理解读写—ReadWriteLock源码分析

    万次阅读 多人点赞 2017-04-24 09:00:54
    ReadWriteLock管理一组,一个是只读的,一个是写。读可以在没有写的时候被多个线程同时持有,写是独占的。 所有读写的实现必须确保写操作对读操作的内存影响。换句话说,一个获得了读的线程必须能...
  • 面试必备之乐观与悲观

    万次阅读 多人点赞 2018-07-16 22:34:26
    推荐阅读: 如何在技术领域持续成长 后端程序员必备的Linux基础知识 ...这种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 悲观 总是假设最坏的情况,每次去拿数据的时候都认为...
  • ZooKeeper框架Curator分布式实现及源代码分析

    千次阅读 多人点赞 2018-11-09 13:25:27
    本原创入门教程,涵盖ZooKeeper核心内容,通过实例和大量图表,... ZooKeeper框架Curator分布式实现及源代码分析 zookeeper 开发实战(java客户端) 上一篇文章中,我们使用zookeeper的java api实现了分布式排...
  • Java并发:线程安全与优化

    千次阅读 2018-01-01 18:25:15
    一个线程对立的例子是Thread类的suspend()和resume()方法,如果有个线程同时持有一个线程对象,一个尝试去中断线程,另一个尝试去恢复线程,如果并发进行的话,无论调用时是否进行了同步,目标线程都是存在死锁...
  • Redis命令SETNX的使用(包含Java分布式实现) 可以参考Redis官网对SETNX命令的介绍: https://redis.io/commands/setnx SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key ...
  • MySQL详解

    万次阅读 多人点赞 2019-06-05 16:28:50
    根据加锁的范围,MySQL里面的大致可以分成全局、表级和行锁三类 一、全局 全局就是对整个数据库实例加锁。MySQL提供了一个加全局读的方法,命令是Flush tables with read lock。当需要让整个库处于只读...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 154,232
精华内容 61,692
关键字:

两段锁例子

友情链接: kuaipai.rar