阅读以下关于数据库设计的叙述,在答题纸上回答问题1至问题3。
某航空公司要开发一个订票信息处理系统,以方便各个代理商销售机票。开发小组经过设计,给出该系统的部分关系模式如下:
航班(
航班编号
,航空公司,起飞地,起飞时间,目的地,到达时间,剩余票数,票价)
代理商(
代理商编号
,代理商名称,客服电话,地址,负责人)
机票代理(
代理商编号
,
航班编号
,票价)
旅客(
身份证号
,姓名,性别,出生日期,电话)
购票(
购票单号
,
身份证号
,
航班编号
,搭乘日期,购票金额)
在提供给用户的界面上,其核心功能是当用户查询某航班时,将该航班所有的代理商信息及其优惠票价信息,返回给用户,方便用户购买价格优惠的机票。在实现过程中发现,要实现此功能,需要在代理商和机票代理两个关系模式上进行连接操作,性能很差。为此开发小组将机票代理关系模式进行了扩充,结果为:
机票代理(代理商编号,航班编号,代理商名称,客服电话,票价)
这样,用户在查找信息时只需对机票代理关系模式进行查询即可,提高了查询效率。
问答题
机票代理关系模式的修改,满足了用户对代理商机票价格查询的需求,提高了查询效率。但这种修改导致机票代理关系模式不满足3NF,会带来存储异常的问题。 1)请具体说明其问题,并举例说明。 2)这种存储异常会造成数据不一致,请给出解决该存储异常的方案。
【正确答案】正确答案:具体问题有数据冗余和更新异常。 数据冗余:代理商名称和客服电话存在于两个关系模式,而且机票代理关系模式中,该代理商代理了多少个航班,则代理商名称和客服电话被重复存储多少次。 更新异常:当代理商名称或客服电话变更时,不仅需要修改代理商关系模式,还需要修改机票代理关系模式,否则会造成数据不一致。 可采用两种方案实现。 (1)通过程序实现,当修改代理商关系模式数据时,程序同步修改机票代理关系模式; (2)通过触发器实现,在代理商关系模式上加修改触发器,当修改代理商关系模式数据时,程序同步修改机票代理关系模式。
【答案解析】解析:本问题考查数据库设计中关系范式规范化和反规范化的相关知识。众所周知,关系范式规范化的结果是关系越来越小,关系范式的概念越单一。但是要解答用户的问题,往往会涉及到多表关联操作,影响查询效率。因此应用中经常采用反规范化的方法来提高查询效率。因此开发小组对机票代理关系模式的修改属于反规范化。 但是反规划带来的直接结果是数据冗余存放,如题干描述的机票代理中,代理商名称和客服电话数据就存在于机票代理和代理商两个模式中。这种情况会引起更新异常,比如当代理商名称或客服电话变更时,不仅需要修改代理商关系模式,还需要修改机票代理关系模式,否则会造成数据不一致。 要解决范式规范化带来的问题,主要是保持两个地方存储数据的一致性。常见的方法有两种:一种是通过程序实现,在业务程序中,当修改代理商关系模式数据时,程序同步修改机票代理关系模式;另一种是通过触发器实现,在代理商关系模式上加修改触发器,当修改代理商关系模式数据时,程序同步修改机票代理关系模式。
问答题
在机票销售信息处理系统中,两个代理商的售票并发执行,可能产生的操作序列如表4.1所示。
【正确答案】正确答案:1)第一个代理商能够正确售票。第二个代理商查询剩余票数时正确,为1张机票,但剩余票数减一操作时出错,因为该机票已经被第一个代理商售出,此时第二个代理商无票可售。 2)并发操作会带来数据不一致问题,具体为:丢失修改、读脏数据、不可重复读。
【答案解析】解析:本问题考查数据库设计中的并发问题和数据库事务隔离级别的基本概念。数据库为众多用户同时提供服务,如果多个用户产生了对同一个数据的并发读取操作,就会产生并发问题。 表4-1描述的是并发的一种可能情况,在允许脏读的条件下,第一个代理商能够正确售票。第二个代理商查询剩余票数时正确,为1张机票,但剩余票数减一操作时出错,因为该机票已经被第一个代理商售出,此时第二个代理商无票可售。 并发问题会造成数据的不一致。在数据库事务隔离级别定义中,定义了并发问题会造成的三种现象,分别是丢失修改、读脏数据和不可重复读,而根据这三种现象,划分了4种不同的事务隔离级别。
问答题
为了避免问题2中的问题,开发组使用了数据库的读写锁机制,操作序列变为表4.2所示。
【正确答案】正确答案:(1)加写锁(2)加读锁(3)加写锁(4)被阻塞(5)得到通知 (6)加写锁 读写锁的缺点:读写锁会造成读写操作的互相阻塞,实际使得用户的操作被串行化,降低了系统的并发性能。设计不好的情况下,可能会出现资源的交叉锁定,形成死锁。
【答案解析】解析:本问题考查数据库中基本的读写锁机制,通过提供读锁和写锁的相互阻塞,来解决并发问题。锁机制的基本概念是读取操作之前先加锁,成功后方能读写数据。读操作加读锁,写操作加写锁。读锁会阻塞写锁,即加了读锁的数据,在未释放读锁之前不能加写锁,可以加读锁;同样,写锁会阻塞读锁,在写锁未释放前,不能再加读锁和写锁。其实质是使得相互冲突的并发读写操作,变为串行化读写操作,来解决并发问题。 因此,根据读写锁的基本机制,表4.2中的空应该填写的内容是(1)加写锁、(2)加读锁、(3)加写锁、(4)被阻塞、(5)得到通知、(6)加写锁。