李大明
(铁道部 信息技术中心,北京 100844)
随着嵌入式系统的广泛应用及用户对数据处理和数据管理能力的不断提高,嵌入式数据库技术得到快速发展。嵌入式数据库不仅具有传统数据库的主要功能,还具有操作简单、快捷灵活等特性。该技术屏蔽了传统数据库需要与服务器配置相关的资源开销,可以直接嵌入到应用进程中,对数据库进行处理。基于嵌入式关系数据库存储的货运杂费收缴管理系统可以提高货运杂费收缴的效率,加快铁路货运管理信息化的进程,已成为铁路货运现代化管理的中坚力量。
铁路货物运输杂费是铁路货物运输费用的组成部分。货物自承运至交付的全过程中,铁路运输企业向托运人、收货人提供的辅助作业和劳务,以及托运人或收货人额外占用铁路设备,使用用具、备品所发生的费用等,均属货运杂费。
铁路货运杂费收缴系统具有到达货票接收、发送杂费补收、到达货物交付、杂费核收、客户预付款管理、催领通知打印、进款结账、分类统计等功能。对装卸费的核收,货车使用费的核收,取送车费的核收、内外勤交接等提供专用处理模块。满足车站多样化的需求。
货运杂费收缴系统作为基础杂费收缴工具,在基层分为单机工作模式和服务器工作模式,同时对铁路局、铁道部层次具有传输接口,其体系结构如图1。
1.3.1 软件登陆
进入本系统的接口,校验用户名称、口令,用户登录需要选择工作日期,校验成功后进入系统。
1.3.2 系统设置模块
系统设置模块完成一组与本系统运行信息相关的功能,包括:业务岗位设置、操作员设置、系统运行车站设置、系统运行模式设置、修改当前操作员口令、变更操作员和系统日志查询等功能。
1.3.3 到达处理模块
完成到达货票接收、到达货票录入、到达货票确认、到达货票催领和到达货物交接等操作。
1.3.4 业务处理模块
在货票完成到达处理作业环节后,即进入业务处理环节,包括:到达运杂费核收、发送运杂费核收、中间运杂费交付、货车使用费交付。
1.3.5 统计报告模块
该模块完成各种统计报表,包括:各种业务的浏览和统计。
1.3.6 预付款处理模块
该模块处理的是在到达运杂费核收模块中付款方式选择预付款交付产生的杂费信息。预付款管理包括预付款存入、支付明细查询、预付款扣款、预付款退补和预付款结帐等内容。
1.3.7 参数维护模块
参数字典维护是本系统中所涉及到的所有字典参数的维护。
货运杂费收缴管理系统的本地存储采用开放源代码的嵌入式关系数据库SQLite,整个数据库(定义、表、索引和数据本身)都存储在一个单一的文件中,不需要管理员进行数据库软件的维护。而网络存储采用Oracle8i同时支持Oracle7、Oracle9i版本数据库。下面重点介绍本系统中本地存储的嵌入式关系数据库设计。
嵌入式数据库在某些方面与大型关系数据库相似,它最大的特性是无须拥有独立运行的数据库引擎,具有占用磁盘小,占有内存少的特点。实际上嵌入式数据库是一种具备了基本数据库特性的若干数据文件。嵌入式数据库编译后的产品所占内存一般不超过几十kbit。
嵌入式数据库将数据库系统与操作系统和具体应用集成在一起,运行在各种智能嵌入式设备上。与传统的数据库系统相比,它体积小,有较强的便携性和易用性,以及较为完备的功能来实现用户对数据的管理操作。在实际应用中,嵌入式数据库存储容量较小、稳定性和可靠性比较低,我们可以在PC机上配置嵌入式数据库来实现大容量数据的存储和管理。
从结构上可以将嵌入式数据库管理系统分为外壳和内核两大部分。
2.2.1 外 壳
嵌入式数据库提供可直接调用的内部接口函数,开发人员可以通过接口函数对数据库直接进行管理和访问。数据库应用程序是数据管理体系与终端的中间层,数据库应用开发人员在本层进行编码工作,完成对嵌入式数据库的访问链接。
开发人员在使用数据库系统向上提供的接口函数时,只需要调用标准的接口,不需要考虑下层的实现细节。其主要工作是对接口函数的输入项进行处理,然后将需要处理的输入项转化为数据库内部可处理的数据结构。
2.2.2 内 核
这部分是嵌入式数据库的内核,包含了嵌入式数据库的核心功能。主要有:系统管理、事务管理器等。具体内容本文不做详细介绍。
本系统存储工具采用了开放源代码的SQLite嵌入式关系数据库,在基于源代码的基础上定义了一些结构性的宏,这样既可以支持中间层的接口定义,也方便调用管理。而在数据存储中采用压缩、加密技术,通过中间层对原始数据进行压缩及加密。上层的应用进程通过调用中间层实现对数据的访问,保护原始数据不被恶意篡改,因而保证了数据的安全性和完整性。数据结构如图2。
图2 数据结构
2.3.1 设计策略
整个数据存储涉及到的两种数据:字典数据和业务数据。设计策略包含数据存储策略、数据访问策略等。
2.3.1.1 数据存储策略
针对不同的数据采取不同的存储方案:(1)对于字典数据,按照不同的维护层次(部级字典、局级字典、站段级字典(含地铁公司)、窗口级字典)分别存储到相对独立的本地数据文件中,窗口级字典不上传到网络,其他字典在网络上分开存放,每一级维护的参数原则上存储在一个该级对应的本地数据库中。(2)对于杂费业务数据,本地按照工作日分开存储,网络按工作库/历史库存储,工作库保存1个月~2个月,历史库保存1年~2年。为保证数据的安全性和完整性,本地数据存储在两个不同的目录下,每次写数据时同时写入两个本地数据库,如果网络存储状态正常,同步写入网络数据库,有服务器而网络不通时,把数据的变化写入日志,待网络连通时,自动实现数据上传到网络服务器。本地数据与工作库由接口程序实现同步,工作库到历史库由具有管理权限的操作员控制数据倒库。
2.3.1.2 数据访问策略
字典数据每个维护层次只能修改自己负责的数据,对于由其他层次维护的字典数据只能读取。
业务数据来自最基层,所以只能由车站级杂费软件建立和修改,其他授权系统只能读取,未授权系统不能读取。业务数据只能从窗口本地上传到服务器,不允许服务器数据覆盖本地数据,恢复客户机时应有管理员权限。
查询数据时,根据系统运行模式确定所要查询的数据库是本地数据库还是网络数据库。
货票本地数据库文件、杂费本地数据库、字典本地数据库分别在不同的目录中存储。
网络数据库中数据表名称由电报码和标识符号组成(不按时间区分表名)。本地数据库中表名与网络服务器表名相同。
2.3.2 数据元素
货票数据包含本站发送货票和到达货票,也包括地铁公司运行的货物在到站填制的货票。
接收电子票直接存入工作库,接收时比较数据状态,如果库中数据已经做过处理,不能直接进行覆盖。数据元素主要包括货票数据、杂费数据、部级字典、局级字典、站段字典、操作日志。具体数据结构省略。
3.1.1 数据结构
货运杂费收缴管理系统根据嵌入式数据库基本功能的特点,将系统中所有的数据分为数据表、数据表索引和资源队列。并由此定义了相应的数据对象:二维表对象、表索引对象和队列对象。对于每一种对象,都有相应的特征描述来规定该对象的共有特性以及实现的基本方法。
3.1.2 存储管理实现
货运杂费收缴管理系统的数据库由若干表组成,每个表对应的表空间在内存中采用虚拟文件来存储,通过对存储空间的起始地址、结束地址及链表的记录管理,实现对这些表的存储空间进行有效的管理。把这些虚拟文件的连续存储空间按页面存储,每个页面可以存储多条记录。对于页面大小的处理,可以根据记录的大小及记录数来控制。因此,当对数据库中一条记录进行修改操作时,只需要将虚拟文件中这条记录所在的页面修改即可。
3.1.3 提供的接口函数
cache_init 缓冲初始化:为表分配页面,并将该表加入到缓冲表中,同时初始化。
cache_free 清空缓冲区:释放表的所存在的页面,然后释放表所占的缓存。
cache_load 文件装载:从磁盘中将表对应的文件数据全部读到表的相应页面中。
cache_write 写入文件:将表中的节点链表中数据写到对应磁盘的文件。
cache_addpg 扩展节点:添加一个新节点。cache_delpg 删除节点:删除节点。
cache_redpg 读取一页:从数据中读取指定一页内容。
cache_outpg 写入一页:将指定一页数据写到文件中。
嵌入式数据库SQLite的C语言API以下面3个核心函数为基础:
sqlite *sqlite_open(const char *dbname,int mode,char **errmsg);
Void sqlite_close(sqlite *db);
Int sqlite_exec(sqlite *db,char *sql,int(*callback)(void *,int,char **,char**),void *parg,char**errmsg);
其中,前两个函数用于打开与关闭数据库,sqlite_exec函数用来处理sql查询,所用callback函数由用户编写,用来接收查询结果,查询结果的每一条记录都会调用一次callback函数,正常返回0,如果非0,则查询失败。
杂费收缴管理系统基于SQLite提供的接口函数封装了一个中间层,该层完成了对数据的压缩和编码加密,然后存入数据库。所以,用标准SQL语言从数据库中查寻的结果是乱码,只有通过中间层访问,解压缩再解密后才能得到原始数据,这样就保证了数据的安全性和完整性。其中,编码采用Base64编码,Base64编码把任意序列的字节描述为一种不易被人直接识别的形式。通过编码和加密后的数据所占的存储空间变大,所以利用压缩技术减少数据所占的空间。
中间层分别定义了压缩和加密函数,如下:
compress(Bytef *dest,uLongf *destLen,const Bytef *source,uLong sourceLen);
int Base64Encode(const unsigned char *src,int srclen, unsigned char *dest);
使用Base64Encode函数时,应注意要分别记录数据压缩前后的长度,否则在解压时无法还原。
中间层中还定义了数据库相关类CppSQLite3DB和CppSQLite3Statement。类中的方法基于SQLite提供的API函数,构造了对数据库访问的实现。
举例说明插入表的代码如下:
通过以上代码就完成了杂费收缴管理系统中对原始数据进行压缩、编码再插入到数据库表的功能实现。同样,可以完成对嵌入式数据库中数据的删除和更新等功能的实现。
3.3.1 事务管理的实现
货运杂费收缴管理系统将所有任务的事务状态分为3种:开始提交(向系统文件提交修改过的数据页面)、正在提交(向数据文件提交修改过的数据页面)和事务空闲(没有开始事务)。事务处理包括开始事务、提交事务、事务回滚等功能。当事务回滚时,将任务日志中所有修改过的数据页面回退,把修改的记录还原。当提交事务时,将任务日志中修改过的数据页面写入到系统日志文件中。多个任务的事务同时提交时,事物彼此间是互斥的,优先处理优先级高的事物。
3.3.2 日志设计与实现
货运杂费收缴管理系统中存在两种日志:系统日志文件和任务日志,系统日志文件只有一个,用于处理并发事物时使用;而任务日志文件每个任务生成一个,用于记录本任务的修改操作。对于每一个事物,都有一个日志记录任务所修改过的虚拟文件和数据页面号。当提交事务时,依据任务日志记录的内容记入系统日志文件,当回滚事务时,依据任务日志恢复所有修改过的数据页面。
基于嵌入式关系数据库存储的货运杂费管理系统技术先进、结构合理、功能完善、安全可靠。该系统的使用有助于降低铁路运营成本、强化精细管理、提高作业效率,为铁路货运服务提供了强有力的保障。
[1]铁道部. 铁路货物运输规程[M]. 北京:中国铁道出版社,2011,4.
[2]铁道部. 铁路货物运输管理规则[M]. 北京:中国铁道出版社,2000,9.
[3]铁道部. 铁路运输收入票据管理工作规则[M]. 北京:中国铁道出版社,2003,1.
[4]解 辉. 嵌入式数据库实现原理[DB/OL]. http://www.docin.com/p-332516826.html, 2008-07-01.