科技时代新浪首页 > 科技时代 > 滚动新闻 > 正文

海关数据库系统建设借鉴


http://www.sina.com.cn 2006年07月26日 10:37 中国计算机报

  作者:全国海关信息中心 王翔

  创新性应用

  数据库技术的生命力和其所能服务的应用类型有直接的关系,同时一个数据库产品能否在市场中胜出,很大程度上也取决于它对各类应用开发的支持程度。在此我综合新应用
类型和新应用开发支持两个方面来谈数据库技术的创新性应用。

  正在实施的新一代物流系统中,空间数据库、图像识别技术都会被采用。空间数据库结合GPS技术用于跟踪实际运行的物流工具;用射频和超声波技术对货物在集装箱的物理位置和实际介质类型进行检查,这里的检查涉及的数据比对不仅仅是简单关系数据比照,还包括空间数据的比照;图像识别技术主要用户对电子车牌等信息的记录,以往这类数据一般都保存为图像,但是非常不利于检索和查询、统计,因此需要通过图像识别提取出具体的牌照编号,变二进制对象为字符串。

  由于海关的作业现场分布非常广,对于很多远场的查验工作使用PC设备不太现实,为此需要通过手持智能设备进行类似的查验工作。为了保存底账之类的信息则需要使用到嵌入式移动数据库,与以往桌面数据库、集中数据库不同,移动数据库的同步问题成为一个比较棘手的问题,此外本人认为更加值得关注的问题是如何保持在一个时断时续环境下的分布式交易的问题,暂时处理方法是“对帐 + 二次提交”,这个原理非常类似以前的EDI处理,无论是移动方还是服务器端都通过报文(实际使用得很可能是短信)确认交易操作内容和操作数据,在完成后都向对方发送处理结束的回执(正常或者异常、失败等),双方都需要根据回执判断是否可以正常入库。当然,考虑到报文的延迟,这里还要增加超时机制。

  业务处理规则表达式化,业务处理流程工作流化。在某些业务环节,对于数据的处理和审核规则是非常多变的,如果通过硬编码实现那么意味着应用需要非常频繁的更新和下发,尤其对于一个全国性系统而言则对运维影响很不好,通过不断改进表达式引擎,海关把这些审核规则表示为业务化的表达式,例如:“原产地([国籍]) && [税率] < 0.1”,这里[]的内容代表单据的字段,原产地()代表业务化函数,这些表达式保存在数据库中,在业务环节执行的过程中由表达式引擎动态的执行。同样,由于同样的工作在不同海关由于部门职能设置的不同,处理流程也有所不同,例如:IT故障在不同海关的通报机制就差别很大。因此在保证每个业务环节(Step)的表达式化外,还要提供处理流程的工作流化,来更多的避免重新集成测试、打包下发的工作。

  考虑到集成数据库产品的供应商风险(价格、服务、后续技术支持等因素),因此对于产品型软件软件和大型的核心应用系统,只要有条件都要考虑增加Provider Independent的数据访问层,该访问层不仅需要提供常规SQL语句的支持、还要提供存储过程、触发器、视图、嵌入表等数据库对象的支持,尽量不要把自己的产品和系统绑死在某个具体的数据库产品上。

  在非核心业务系统上,更多的走纯XML数据的道路,通过X-Query把关系数据的操作结果XML化,在其后的应用中通过基于“XSD-XSLT-XSD”的转换体系面向不同的应用,并且在此基础之上完成整个行业的基于XML数据的开发框架和开发库。将LDAP、XML等树形数据看作具有层次关系的二维数据,为他们开发独立的具有层次特性的数据访问驱动,保证可以用普通的二维视图展示层次型数据某个层次的内容。

  为了更好地面向业务服务、主动向业务人员提供必要的数据信息,采用数据库作为暂存机制,更多的以“出版/预定”方式向用户提供数据服务,可以发布的数据服务、用户预定的事件、根据预定生成的结果全部通过数据库保存。无论是内审还是监控的需要,所有的操作流程记录完善的工作流记录,与简单流水账日志不同,对于敏感的操作还需要结合安全系统增加签名保证关员、用户对自己的操作负责,对于关键的业务数据也提供数字签名,保证数据在不同应用间交换、处理的时候,接收方可以对数据的真实性和完整性做出明确的技术判断。

  行业借鉴经验

   首先是数据库的选择上,对于资深企业级或者行业级的架构师(而非某个应用的架构师),数据库选择上要本着实事求是的原则,不拘一格的使用主流商用数据库、主流商用数据仓库、主流桌面数据库、开源数据库、嵌入数据库。自身不要用有色眼镜看待不同的产品(毕竟全球而言,各个数据库能发展至今,就说明他们已经都变成了领域内的多面手),要在用户当前业务需要加之未来1、2年发展的评估基础上,权衡数据库许可成本和应用成本之后,向用户提供恰当的数据选项。

  数据库的布局上也要尽量按照数据的属地特性布局,不要盲目的作“大集中”或者“完全分布”,作为资深架构师您还要了解到PC数据库、开源数据库的成本已经降低到了一个非常低的水平,与其把所有的数据全部保存到一个集中的数据库,不如根据实际情况将部分支持性数据、中间性数据、甚至一些日志信息业都放置到距离应用现场较近的应用服务器的附近。对于企业核心应用而言,如果您的单据普遍数据项非常多,而且客户端的数据相关性检查也比较多,那么完全可以考虑采用胖客户端或者SmartClient,同时为了用户操作的友好,完全可以考虑把许多参数数据(例如:国家代码表、地区代码表、货币代码表、运输方式代码表等)通过逐级下推的方式,放置到客户端,保存在桌面数据库中。总而言是,数据库布局上如果与用户具体要求不明显冲突的情况下,要充分利用到各个层次的数据库计算能力。

  由于现在的很多大型商用数据库不仅仅提供了原有RDBMS的管理功能外,还普遍提供了集成、报表、通知、分布式交易的支持,这里很多功能如果自己开发则很可能成本上或者功能上不合算。因此,即使考虑整个环境采用开源数据库,也最好在应用的边界上考虑部署个别商用数据库产品,一方面有可能通过商用数据库既有功能节省整体开发成本,另一方面在应用于其他应用集成的同时,也可以有效的通过这些商用数据库产品降低运行维护成本。

   面对数百个系统的成百上千个数据库系统,一定要采用区域化——“分而治之”,毕竟对于政府或者企业而言普遍拥有多个信息系统是现状,但是如果想做数据库管理首先第一步要区分哪些是必须7*24小时保障的,哪些仅是偶尔用之前检查一下就可以的,在明确了不同数据库对于企业重要性之后,我们应该将他们划分到不同的区域(Domain),然后根据不同的区域制定不同的IT保证措施,其中要包括:巡检、存储、备份/恢复、电源保证、物理位置保证等。

  在数据库系统的运行维护问题上,本人完全赞同基于业务价值的评估体系,而不仅仅是数据库监控工具所能显示的面向某个技术领域的评估体系,诚然技术故障对于业务系统都有可能是灾难性的,但是对于一个高可用加上异地复制的环境中,可能并不是那么严重,因此我们对于运行故障的评估不应该单纯基于技术上的,而应该更多的是每个数据库对于业务价值的影响上来评估和处理。一方面,可以保证技术人员和公司的高层有了更直接的沟通手段,无论是制作IT发展计划、评估IT自身价值都有了共同的标准;另一方面,在多点故障时,也可以按照对业务的影响合理调配有限的IT支持人员。

  在讨论完技术和维护问题之外,本人愿意谈一下“人”的因素。就像我们的应用系统有核心应用和非核心应用一样,数据库管理人员也要有批次,既要有资深的dba,也要有负责日常管理的dbo(操作员),本人认为人力帐要算总的人力成本;分工上由于数据库管理和存储的天然联系,岗位上可以单独设置,但是为了人员储备和故障应急的考虑,要鼓励两个岗位人员的技术融合;每个故障处理必须有详细的技术处理过程记录,并且要确保让数据库管理人员了解;大型的数据库系统一定要设置技术

审计措施,一方面作为监督手段,警示数据库管理人员、另一方面保护无责任方。

  应用难点技巧

  对于即使通过Expert之类工具还不能很好优化的SQL语句,如何进一步优化?

  对于每一个SQL语句,一般SQL的编译器会尽量采用基于各种既定规则的方式,产生一个较优的查询树(或者称之为执行计划),并且按照这个自认为优化的路径来执行。但是实际SQL语句的处理中,虽然默认数据库会帮助我们生成一个路径,但是在包括多个索引、甚至是不同I/O设备速度的情况下,到底对每一个点的处理使用那个索引或其他控制是可以在商用数据库中用Hint来控制的。

  另外,假如我们的执行目的仅仅是为了尽快的获得前几条符合条件的数据,也可以通过hint告诉RDBMS,然后SQL的解析器就会按照我们查找内容的不同,按照深度或者广度优先算法“不遗余力”的尽量帮助我们快速定位到符合条件的前几条数据。

  对于数据库双向复制中数据反复震荡的处理

  数据库双向复制的震荡指的是数据在目的端提交后,由于继续会生成DML的Redo log,因此如果不加控制,这个操作又会马上转向到源端,进而形成震荡。如果不加控制,这种震荡不仅大量浪费网络、数据库、存贮资源,更主要的是他会使复制后结果出错。

  为此,一定要在双向复制的时候,配置loop detection(不同数据库名称稍有不同)的开关,让复制请求是带着状态过去的,复制后立即修改对应的状态值,这样来避免震荡。

  对于超过两个数据中心相互复制则更加容易出现震荡,为此本人都自己建立一个n*n的配置表,这样即便同时包含双向复制、单向复制也一目了然,不至于混乱。

  对于双向复制中如何处理Identity(自增字段):

  对于类似“计数器”类的Identity(自增字段)如果在复制中不加控制,则会出现翻倍增长的情况。

  这里采用奇偶交替的方法实现,即在准备实施复制的时候,手工将两个点间的数据库通过快照生成一个副本并导入后,人为的影响一面的Identity为奇数 2n +1 ,另外一个Idnetity为 2n,但是Identity字段本身不参与复制。这样,当复制执行的时候,虽然在各方执行的时候都是按照2为递增量继续,而且可以保证数据的正确性。

  对于异构数据库间,分布式死锁的处理:

  异构数据库间的分布式死锁主要出现应用逻辑处理分布式交易的过程中,类似单一数据库的死锁,如果一个应用中不同流程间对分布式数据库的访问不是尽量按照同一个次序执行,则较容易出分布式死锁,虽然分布式死锁出现的概率更低,但是一旦出现由于不能被单一数据库判定是否可以立即裁决掉,所以一旦出现危害将大大超过单一数据库内部出现的死锁,常常是灾难性的。

  由于现有的监控工具基本上没有诊断异构数据库间分布式死锁的功能,这里笔者根据以往经验介绍一下处理步骤:

  1)对于较为正式的业务处理过程,一般

开发商都会提供处理的交易性。

  2)通过从应用服务器检查其netstat(以NT服务器为例),如果发现该应用同时建立了和不同位置不同数据库实例间的网络连接,且通过性能监控器发现cpu维持在较低的水平,但是应用持续不处理单据,则基本上可以判断可能出现了死锁;但是如果中断后续请求的提交,系统的持续维持在僵持状态,看不出死锁中某个参与对象被裁决的现象,则很可能是分布式死锁;但是打开每个数据库都没有发现提示死锁,只是看到长时间pending的交易,则基本上可以判断出现了异构数据库间的分布式死锁。

  3)根据本人的经验,虽然每个数据库对于自己内部的rollback可以很好的保证,但是对于异构(甚至是同一数据库产品的不同版本间)数据库则rollback后全部恢复原样不是那么有谱,因此本人还是建议从应用服务器端abort交易。

  4)处理个别异构分布式死锁不算麻烦,但是要更好的避免它的出现,最好的办法还是要保证分布式交易(应用代码或者存储过程)过程的对象访问次序一致性,且对于应用逻辑组件定义合适的timeout。

  在使用分区表的情况下,尽量慎重使用Union:

  由于Union的操作实质上是SELECT DISTINCT,因此如果可以基本确定每个SELECT后的数据集和另一个数据集不会出现非空交集的时候,最好不用Union。尤其对于Union的对象是按照SELECT子句子段集合分区后的分区表,这些Union操作完全可以在应用逻辑层、甚至是客户端完成。

  尽量使用case-sensitive的数据库:

  本人从事的主要项目都采用Case-sensitive的数据库,原因就一个——“效率”,虽然对于很多开发人员而言让他编写case-sensitive的SQL语句会很别扭,但是本着对最终产品负责的原则,本人还是坚持认为尽量使用case-sensitive的数据库。

  用trigger生成常常修改且又常常使用的统计量:

  有些数据变化比较频繁,但是应用又常常需要对其统计量进行查询,例如:“截至现在的投票量”、“某个易耗产品的可用百分比”等,对于这种数据本人一般都额外建个表,通过在该数据项上配置trigger来准实时的更新统计量,而在读取统计量的时候一定要增加with (nolock)之类的不上锁hint来读取当前的统计值。

  对交易内处理步骤的安排:

  对于每个步骤没有绝对次序关系的交易而言,本人始终坚持“越易出错的越写在前面”原则

发表评论

爱问(iAsk.com)



评论】【论坛】【收藏此页】【 】【多种方式看新闻】【下载点点通】【打印】【关闭




科技时代意见反馈留言板 电话:010-82628888-5595   欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

Copyright © 1996 - 2006 SINA Inc. All Rights Reserved

新浪公司 版权所有