数据库 - 并发调度的可串行性

并发调度的可串行性

DBMS对并发事务不同的调度(schedule)可能会产生不同的结果

什么样的调度是正确的?

串行化(Serial)调度是正确的

对于串行调度,各个事务的操作没有交叉,也就没有相互干扰,当然也不会产生并发所引起的。如前所述,事务对数据库的作用是将数据库从一个一致的状态转变为另一个一致的状态。多个事务串行执行后,数据库仍旧保持一致的状态。

可串行化(Serializable)调度

多个事务的并发执行是正确的,当且仅当其结果与按某一次序串行地执行这些事务时的结果相同。可串行化调度当然也保持数据库的一致状态

[例]现在有两个事务,分别包含下列操作:
事务T1:读B;A=B+1;写回A
事务T2:读A;B=A+1;写回B
现给出对这两个事务不同的调度策略

可串行性(Serializability)

是并发事务正确调度的准则。在RDBMS中,作为并发控制的正确性准则。一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度

可串行化调度的充分条件

一个调度Sc在保证冲突操作的次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个调度Sc‘,如果Sc’是串行的,称调度Sc为冲突可串行化的调度

一个调度是冲突可串行化,一定是可串行化的调度

一般RDBMS都将冲突可串行化作为并发控制的正确性准则

冲突操作(Conflict Operation)

冲突操作是指不同的事务对同一个数据的读写操作和写写操作

Ri (x)与Wj(x) /* 事务Ti读x,Tj写x*/

Wi(x)与Wj(x) /* 事务Ti写x,Tj写x*/

其他操作是不冲突操作

不同事务的冲突操作和同一事务的两个操作不能交换(Commute) ,否则会影响执行的效果

[例]今有调度Sc1=r1(A)w1(A)r2(A)w2(A)r1(B)w1(B)r2(B)w2(B)
把w2(A)与r1(B)w1(B)交换,得到:
    r1(A)w1(A)r2(A)r1(B)w1(B)w2(A)r2(B)w2(B)
再把r2(A)与r1(B)w1(B)交换:
   Sc2=r1(A)w1(A)r1(B)w1(B)r2(A)w2(A)r2(B)w2(B)
Sc2等价于一个串行调度T1,T2,Sc1冲突可串行化的调度
冲突可串行化调度是可串行化调度的充分条件,不是必要条件。还有不满足冲突可串行化条件的可串行化调度,称为目标可串行化(view serializability)的调度。
    [例]有3个事务, L1和L2是目标等价的(view equivalence)
       T1=W1(Y)W1(X),T2=W2(Y)W2(X),T3=W3(X)
调度L1=W1(Y)W1(X)W2(Y)W2(X) W3(X)是一个串行调度。
调度L2=W1(Y)W2(Y)W2(X)W1(X)W3(X)不满足冲突可串行化。但是调度L2是可串行化的,因为L2执行的结果与调度L1相同,Y的值都等于T2的值,X的值都等于T3的值

封锁协议

 运用封锁方法时,对数据对象加锁时需要约定一些规则

何时申请封锁

持锁时间

何时释放封锁等

两段封锁协议(Two-Phase Locking,简称2PL)是最常用的一种封锁协议,理论上证明使用两段封锁协议产生的是可串行化调度

两段锁协议

指所有事务必须分两个阶段对数据项加锁和解锁

在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁

在释放一个封锁之后,事务不再申请和获得任何其他封锁

“两段”锁的含义

事务分为两个阶段

第一阶段是获得封锁,也称为扩展阶段

事务可以申请获得任何数据项上的任何类型的锁,但是不能释放任何锁

第二阶段是释放封锁,也称为收缩阶段

事务可以释放任何数据项上的任何类型的锁,但是不能再申请任何锁

例
事务Ti遵守两段锁协议,其封锁序列是 :
Slock A    Slock B    Xlock C     Unlock B    Unlock A   Unlock C;
|←      扩展阶段    →|  |←      收缩阶段           →|
事务Tj不遵守两段锁协议,其封锁序列是:
Slock A    Unlock A    Slock B    Xlock C    Unlock C    Unlock B;

事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。

若并发事务都遵守两段锁协议,则对这些事务的任何并发调度策略都是可串行化的

若并发事务的一个调度是可串行化的,不一定所有事务都符合两段锁协议

两段锁协议与防止死锁的一次封锁法

一次封锁法要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行,因此一次封锁法遵守两段锁协议

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

封锁粒度(Granularity)

封锁对象的大小称为封锁粒度(Granularity)

封锁的对象:逻辑单元,物理单元

例:在关系数据库中,封锁对象:

逻辑单元: 属性值、属性值集合、元组、关系、索引项、整个索引、整个数据库等

物理单元:页(数据页或索引页)、物理记录等

封锁粒度与系统的并发度和并发控制的开销密切相关。

封锁的粒度越大,数据库所能够封锁的数据单元就越少,并发度就越小,系统开销也越小;

封锁的粒度越小,并发度较高,但系统开销也就越大

若封锁粒度是数据页,事务T1需要修改元组L1,则T1必须对包含L1的整个数据页A加锁。如果T1对A加锁后事务T2要修改A中元组L2,则T2被迫等待,直到T1释放A。

如果封锁粒度是元组,则T1和T2可以同时对L1和L2加锁,不需要互相等待,提高了系统的并行度。

又如,事务T需要读取整个表,若封锁粒度是元组,T必须对表中的每一个元组加锁,开销极大

多粒度封锁(Multiple Granularity Locking)

在一个系统中同时支持多种封锁粒度供不同的事务选择

选择封锁粒度

同时考虑封锁开销和并发度两个因素,适当选择封锁粒度

需要处理多个关系的大量元组的用户事务:以数据库为封锁单位

需要处理大量元组的用户事务:以关系为封锁单元

只处理少量元组的用户事务:以元组为封锁单位

多粒度树

以树形结构来表示多级封锁粒度

根结点是整个数据库,表示最大的数据粒度

叶结点表示最小的数据粒度

允许多粒度树中的每个结点被独立地加锁

对一个结点加锁意味着这个结点的所有后裔结点也被加以同样类型的锁

在多粒度封锁中一个数据对象可能以两种方式封锁:显式封锁和隐式封锁

显式封锁: 直接加到数据对象上的独立封锁

隐式封锁: 该数据对象没有独立加锁,是由于其上级结点加锁而使该数据对象加上了锁

显式封锁和隐式封锁的效果是一样的!

系统检查封锁冲突时

要检查显式封锁

还要检查隐式封锁

例如事务T要对关系R1加X锁

系统必须搜索其上级结点数据库、关系R1

还要搜索R1的下级结点,即R1中的每一个元组

如果其中某一个数据对象已经加了不相容锁,则T必须等待

对某个数据对象加锁,系统要检查

该数据对象

有无显式封锁与之冲突

所有上级结点(祖先)

检查本事务的显式封锁是否与其它事务在该数据对象上的隐式封锁冲突:(由上级结点已加的封锁造成的)

所有下级结点(后裔)

看其它事务在下级节点上的显式封锁是否与本事务的隐式封锁(将加到下级结点的封锁)冲突

数据共享与数据一致性是一对矛盾

数据库的价值在很大程度上取决于它所能提供的数据共享度

数据共享在很大程度上取决于系统允许对数据并发操作的程度

数据并发程度又取决于数据库中的并发控制机制

数据的一致性也取决于并发控制的程度。施加的并发控制愈多,数据的一致性往往愈好

数据库的并发控制以事务为单位

数据库的并发控制通常使用封锁机制

两类最常用的封锁

并发控制机制调度并发事务操作是否正确的判别准则是可串行性

并发操作的正确性则通常由两段锁协议来保证。

两段锁协议是可串行化调度的充分条件,但不是必要条件

时间: 2024-08-02 10:44:30

数据库 - 并发调度的可串行性的相关文章

airflow使用mysql数据库,LocalExecutor并发调度(1)

mysql-airflow 在mysql上执行 create database airflow; —— 创建数据库 GRANT all privileges on airflow.* TO 'airflow'@'%' IDENTIFIED BY '123456'; —— 将数据库airflow的所有权限授权airflow用户,密码123456且该用户可在任何IP段登录操作 FLUSH PRIVILEGES; —— 刷新权限 set explicit_defaults_for_timestamp

数据库并发事务控制 一:综述

并发控制是DBMS的关键技术 对数据库的操作都是在事务中进行的. 事务是指一组相互依赖的操作行为.事务中的操作是不可分割的工作单元,由一组在业务逻辑上相互依赖的SQL语句组成,有ACID特征. Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败. Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态. Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完

SqlIte数据库并发性

把遇到的一些小问题都记下来,告诉自己,一些小细节会铸成打错的 今天没事复习以前的知识,用sqlite做数据库,发现修改数据的时候等好久才有反应,而且还失败,可是过一会之后又会好,好了以后又是一样,种以为是自己的语句有问题,测试了好多次,感觉没问题,在到网上查查错误才发现,原来sqlite不可以并发处理数据,我要说的不是这个问题,一个好的习惯可以避免所有的小问题,前面的解决方法就是把datareader等要释放的释放,关闭的关闭就可以,这本来就是要的,但是自己却没有这么做,这一个小问题纠结了我一个

MySql数据库并发和事务资料汇总

InnoDB多版本并发控制-MVCC http://my.oschina.net/xinxingegeya/blog/208821 MySql并发控制 http://my.oschina.net/xinxingegeya/blog/215417 MySQL之事务 http://my.oschina.net/xinxingegeya/blog/215419 MySql命令行控制事务 http://my.oschina.net/xinxingegeya/blog/296459 MySQL事务隔离级别

在数据库并发情况下避免插入重复数据的一个解决方法

目前公司的项目中碰到一个情况:需要向一个数据表table1中插入记录,该表的结构类似于下面的定义: 列名  类型 是否允许为空 Id int no Area string no AreaIndex int no Name string no 其中Name的值由Area和AreaIndex拼接而成,形式类似于“Area+AreaIndex”.对于相同的Area,AreaIndex从1开始计数,所以对于Area分别为“AA”,“BB”,“CC”的情况,Name的值类似下面这样: AA001 AA00

数据库并发事务控制四:postgresql数据库的锁机制二:表锁

在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提到: 常规锁机制可以参考pg的官方手册,章节和内容见下面 13.3. Explicit Locking http://www.postgresql.org/docs/9.4/static/explicit-locking.html 这节分为:表锁.行锁.页锁.死锁.Advisory锁(这个名字怎么翻译好???

测试数据库并发压力的shell脚本

本节内容:一例用于测试数据库并发压力的shell脚本代码. 例子: #!/bin/bash #********************************# #并发后台运行fun # #for wanggy 2012-01-25 # #note: www.jquerycn.cn # #fun_num fun函数后台运行次数 # #sql_num 每个函数sql运行次数 # #********************************# #数据库变量设置 dbhost=192.168.1

Goroutine并发调度模型深度解析之手撸一个协程池

golanggoroutine协程池Groutine Pool高并发 并发(并行),一直以来都是一个编程语言里的核心主题之一,也是被开发者关注最多的话题:Go语言作为一个出道以来就自带 『高并发』光环的富二代编程语言,它的并发(并行)编程肯定是值得开发者去探究的,而Go语言中的并发(并行)编程是经由goroutine实现的,goroutine是golang最重要的特性之一,具有使用成本低.消耗资源低.能效高等特点,官方宣称原生goroutine并发成千上万不成问题,于是它也成为Gopher们经常

mysql数据库事件调度(Event)

mysql中的事件调度器可以定时对数据库增加,删除和执行操作,相当于数据库中的临时触发器,与Linux系统中的执行计划任务一样,这样就可以大大降低工作量. 1.开启事件调度器 [[email protected] ~]# vim /usr/my.cnf         --在配置文件中加入以下语句启用调度器 event_scheduler=1 [[email protected] ~]# /etc/init.d/mysql restart ERROR! MySQL server PID file