阅读以下技术说明,根据要求回答下列问题。
[说明]
某省会城市××长途汽车售票系统负责所有本地长途汽车站各班次的汽车票销售,并在该省会城市和全省主要地级市设有多个该长途汽车票销售网点,各售票网点使用相同的售票程序。假设售票程序中用到的伪指令如表所示。
伪指令含义
|
| 伪指令 | 说明 |
| R(A,x) | 返回长途汽车班次A当前的剩余汽车票数给变量x |
| W(A,x) | 将当前数据库中长途汽车班次A的剩余汽车票数置为x |
假设某售票网点一次售出n张长途汽车班次A的汽车票,则售票程序的伪指令序列为:
R(A,x),W(A,x~n)
根据上述业务及规则,完成下列问题。
问答题
若两个售票网点同时销售长途汽车班次A的汽车票,在数据库服务器端可能出现如下的调度。
A:R1(A,x),R2(A,x),W1(A,x-3),W2(A,x-2)
B:R1(A,x),W1(A,x-3),R2(A,x),W2(A,x-2)
C:R1(A,x),R2(A,x),W2(A,x-2),W1(A,x-3)
其中Ri(A,x),Wi(A,x)分别表示第i个销售网点的读写操作,其余类同。
假设当前长途汽车班次A剩余15张汽车票,分析上述3个调度各自执行完后的剩余票数,并指出其中错误的调度,简要分析产生错误的主要原因。
【正确答案】调度A结果:13
调度B结果:10
调度C结果:12
调度A和C结果错误,因为破坏了事务的隔离性。一个事务的执行结果被另一个所覆盖
【答案解析】这是一道要求读者掌握并发情况下不同的调度可能产生不同结果的综合分析题。
由题意可知,两个售票网点同时销售长途汽车班次A的汽车票,初始状态下长途汽车班次A的汽车票数量x=15。
对于调度A,售票网点1通过伪指令“R1(A,x)”,获取长途汽车班次A当前的剩余汽车票数15,并赋给本地变量x。而售票网点2也通过伪指令“R2(A,x)”,获取长途汽车班次A当前的剩余汽车票数15,并赋给本地变量x。接着,售票网点1售出3张长途汽车班次A的汽车票,并通过伪指令“W1(A,x-3)”,将当前数据库中长途汽车班次A的剩余汽车票数置为12(即15-3=12)。但是售票网点2售出两张长途汽车班次A的汽车票,并通过伪指令“W1(A,x-2)”,将当前数据库中长途汽车班次A的剩余汽车票数重新置为13(即15-2=13)。
同理,对于调度B,售票网点1通过伪指令“R1(A,x)”,获取长途汽车班次A当前的剩余汽车票数15,并赋给本地变量x。接着,售票网点1售出3张长途汽车班次A的汽车票,并通过伪指令“W1(A,x-3)”,将当前数据库中长途汽车班次A的剩余汽车票数置为12(即15-3=12)。然后售票网点2通过伪指令“R2(A,x)”,获取长途汽车班次A当前的剩余汽车票数12,并赋给本地变量x。最后售票网点2售出两张长途汽车班次A的汽车票,并通过伪指令“W1(A,x-2)”,将当前数据库中长途汽车班次A的剩余汽车票数置为10(即12-2=10)。
同理,对于调度C,售票网点1通过伪指令“R1(A,x)”,获取长途汽车班次A当前的剩余汽车票数15,并赋给本地变量x。而售票网点2也通过伪指令“R2(A,x)”,获取长途汽车班次A当前的剩余汽车票数15,并赋给本地变量x。接着,售票网点2售出两张长途汽车班次A的汽车票,并通过伪指令“W1(A,x-2)”,将当前数据库中长途汽车班次A的剩余汽车票数置为13(即15-2=13)。但是售票网点1售出3张长途汽车班次A的汽车票,并通过伪指令“W1(A,x-1)”,将当前数据库中长途汽车班次A的剩余汽车票数重新置为12(即15-3=12)。
综上所述,只有调度B执行完后的剩余票数是正确的。由于调度A和C破坏了事务的隔离性,一个事务的执行结果被另一个所覆盖,因此调度A和C的执行结果有错误。
问答题
(1)引入相应的加解锁指令,重写售票程序的伪指令序列,以保证正确的并发调度。
(2)封锁对象的大小称为封锁的粒度(Granularity)。结合你的数据库系统工程实践经验,简要叙述选择封锁粒度时必须同时考虑哪些主要因素?并简述封锁粒度与这些主要因素之间的关系。
【正确答案】(1)重写后的售票程序伪指令序列如下
Xlock(A);R(A,x);W(A,x-n);Unlock(A);
(2)①封锁粒度与系统的并发度和并发控制的开销密切相关
②封锁的粒度越大,并发度就越小,但系统开销就越小
③封锁的粒度越小,并发度就越高,但系统开销就越大
【答案解析】这是一道要求读者掌握2PL协议实际应用、封锁粒度与并发度之间关系的综合应用题。
(1)针对题干所给出的伪指令操作序列:R(A,x);W(A,x-n),在事务读取数据之前加SLock()指令,写数据之前加Xlock()指令,并保证读/写锁不交叉,即满足两段锁协议。重写后的售票程序伪指令序列如下:
XLock(A);R(A,x);W(A,x-n);Unlock(A);
(2)封锁对象的大小称为封锁的粒度(Granularity)。封锁的对象可以是逻辑单元,也可以是物理单元。在关系数据库中,封锁对象可以是属性值、属性值集合、元组、关系、索引项、整个索引,以及整个数据库等逻辑单元,也可以是页(数据页或索引页)、块等物理单元。封锁对象可以很大,比如对整个数据库加锁,也可以很小,比如只对某个属性值加锁。X锁和S锁都是加在某一个数据对象上的。
封锁粒度与系统的并发度和并发控制的开销密切相关。封锁的粒度越大,并发度就越小,但系统的开销也就越小;反之,封锁的粒度越小,并发度就越高,但系统开销也就越大。由此可见,在一个系统中同时存在不同大小的封锁单元,供不同的事务选择使用是比较理想的。而选择封锁粒度时必须同时考虑封锁机构和并发度两个因素,对系统开销与并发度进行权衡,以求得最优的效果。通常,需要处理大量元组的用户事务可以以关系为封锁单元,而对于一个处理少量元组的用户事务,可以以元组为封锁单位以提高并发度。
填空题
下面是用E-SQL实现可串行化调度的长途汽车票销售程序的一部分,请补全空缺处的代码。
EXEC SQL SET TRANSACTION ISOLATION LEVEL ______
EXEC SQL SELECT balance INTO :x FROM tickets WHERE flight='A';
printf("长途汽车班次 A 当前剩余汽车票数为:%d/n请输入购票数:",x);
scanf("%d",&a);
x=x-a;
if (x<0)
EXEC SQL ROLLBACK WORK;
printf("票数不够,购票失败!");
else{
EXEC SQL UPDATE tickets SET ______ WHERE_flight='A';
if (SQLCA.sqlcode<>SUCCESS)
EXEC SQL ______;
else
EXEC SQL ______;
}