阅读以下关于数据库设计的叙述,在答题纸上回答问题1至问题3。
某航空公司要开发一个订票信息处理系统,以方便各个代理商销售机票。开发小组经过设计,给出该系统的部分关系模式如下:
航班(航班编号,航空公司,起飞地,起飞时间,目的地,到达时间,剩余票数,票价)
代理商(代理商编号,代理商名称,客服电话,地址,负责人)
机票代理(代理商编号,航班编号,票价)
旅客(身份证号,姓名,性别,出生日期,电话)
购票(购票单号,身份证号,航班编号,搭乘日期,购票金额)
在提供给用户的界面上,其核心功能是当用户查询某航班时,将该航班所有的代理商信息及其优惠票价信息,返回给用户,方便用户购买价格优惠的机票。在实现过程中发现,要实现此功能,需要在代理商和机票代理两个关系模式上进行连接操作,性能很差。为此开发小组将机票代理关系模式进行了扩充,结果为:
机票代理(代理商编号,航班编号,代理商名称,客服电话,票价)
这样,用户在查找信息时只需对机票代理关系模式进行查询即可,提高了查询效率。
机票代理关系模式的修改,满足了用户对代理商机票价格查询的需求,提高了查询效率。但这种修改导致机票代理关系模式不满足3NF,会带来存储异常的问题。
(1)请具体说明其问题,并举例说明。(2)这种存储异常会造成数据不一致,请给出解决该存储异常的方案。
机票代理(代理商编号,航班编号,代理商名称,客服电话,票价)以(代理商编号,航班编号)作为候选码,其中代理商名称、客服电话仅依赖于代理商编号(主码的一部分),这构成了对主码的部分函数依赖,违反2NF;因此不满足3NF。
不满足3NF的关系模式存在存储异常问题,包括数据冗余和修改异常。
(1)数据冗余:如果某代理商代理100个航班的售票,那么在机票代理的关系模式中就要出现100个元组,该代理商的名称、客服电话也随之重复出现100次。
(2)修改异常:由于上述冗余问题,当需要修改该代理商的客服电话时,就要修改100个元组中的客服电话值,否则就会出现客服电话值不一致的现象。
解决存储异常的典型方案是进行模式分解,但在本题中机票代理已是逆规范化的产物,故可使用触发器在修改时,检查并更新对应数据的方式来解决数据不一致的问题。
本题的关键在于指出逆规范化后出现的对码的非主属性依赖问题,并据此解释为什么产生冗余与更新异常。
规范化前(或规范化的正确做法)应将代理商基本信息独立存放于“代理商”表,机票代理表只保留用于描述“代理商×航班”关联与该组合上的业务属性(如优惠票价)。在逆规范化之后,机票代理(代理商编号,航班编号,代理商名称,客服电话,票价)以(代理商编号,航班编号)作为候选码,其中代理商名称、客服电话仅依赖于代理商编号(主码的一部分),这构成了对主码的部分函数依赖,违反2NF;因此不满足3NF。由此带来典型异常:数据冗余(相同代理商信息在多航班记录中重复)、修改异常(单点更新需波及多行;漏改则不一致)、插入异常(尚未有具体航班时无法插入代理商信息)与删除异常(删除某航班代理记录时可能意外丢失该代理商的事实)。例如:代理商X代理了100个航班,客服电话从“400-123-4567”改为“400-765-4321”,若只更新了其中98条,系统中将同时存在两种客服电话,数据不一致直接危害用户联系与对账流程。
在保持性能收益的前提下消解不一致,常见方案有三:其一,回归3NF(机票代理仅保留代理商编号、航班编号、票价;代理商名称与客服电话通过连接获取),可彻底消除异常,但会增加查询连接成本;其二,触发器同步:在“代理商”表上建立AFTER UPDATE触发器,当代理商名称或客服电话变更时,自动UPDATE 机票代理 SET 名称/电话=... WHERE 代理商编号=...,提供数据库内的强一致性与较好的实时性;其三,应用层事务同步:将更新代理商与批量更新机票代理冗余列纳入同一事务,失败则回滚,适合业务逻辑集中在应用层的系统。此外,还可考虑定时批处理(弱一致)、物化视图/索引视图(由数据库维护视图物化数据以供快速查询)或缓存(如Redis)+订阅通知(在变更时失效缓存重建),在读多写少的场景权衡一致性与性能。