1 建立基于客户服务器结构的应用程序
INFORMIX-OnLine 7.1是面向大规模联机事务处理,支持决策应用的高性能的数据库系统,不但具有分布式数据处理功能,还支持客户服务器结构的应用。
我们使用的服务器是HP E25小型机,操作系统是HP_UX 9.04,安装OnLine 7.1。由于OnLine 6.0以上都已内嵌Star,所以不必再安装。客户机为HP NetServer LD,&127;操作系统是SCO OpenServer 5.04,安装OnLine 5.0和传输模块INFORMIX-Net。客户机运行用ESQL/C编写的业务程序,用这样的语句打开服务器上的数据库cbdb:&127;$database icbd@bacct_qz;。
其中acct_qz为服务器的主机名,然后调用存放在数据库系统表中的存储过程来实现整个业务系统,&127;使用存储过程可以减少网络的传输量,当然也可以直接使用SQL语句对数据库进行操作。服务器和客户机上都要建立icbacct用户作为信任用户,用户标识号可以不同。客户机上使用INFORMIX传输模块Net提供的sqlrmtlitcp程序,在用户icbacct的.profile文件中要输出环境变量:&127;SQLEXEC=$INFORMIXDIR/lib/sqlrmtlitcp。
因为INFORMIX-OnLine数据库系统的安全性能依赖于TCP/IP网络协议,所以服务器一般不要在/etc/hosts.equiv文件中配置客户机的主机名,可以仅让客户机上的icbacct用户成为信任用户,方法是在服务器的icbacct 用户根目录下的 .rhosts文件中登记客户机的主机名acct_ha,同时也要在客户机上的icbacct用户根目录下的.rhosts文件登记服务器的主机名acct_qz。这样在客户机上以icbacct用户登录后就可以运行业务程序,还可以用isql直接访问数据库,其他用户如informix用户由于不是可信任的用户就不能访问数据库。由于TCP/IP在检查信任用户时是将所有用户的 .rhosts文件追加在/etc/hosts.equiv文件后面一起判断的,所以如果将服务器上的用户icbacct的 .rhosts文件的内容改为如下:
"acct_ha informix",就可以让客户机acct_ha的informix用户也能访问数据库。
数据库名字有两种格式,一是"数据库名@服务器主机名",在客户机上使用。比如在客户机上以icbacct用户登录后,在使用isql修改数据时输入数据库名"icbdb@acct_qz",其中acct_qz为服务器的主机名。二是"数据库名@数据库服务器名",在服务器acct_qz上使用。比如在服务器上运行的数据库服务器的名字是acct_online,则数据库名是icbdb@acct_online。服务器用户icbacct的.profile文件要输出环境变量INFORMIXSERVER=acct_online。
上述两个数据库名实际上指的都是同一个数据库。
从以上分析不难看出,客户服务器结构在安全上也存在一个隐患,当所有县支行的数据都集中到市行后,在任何一个县行的客户机上都可直接用isql修改其他行处的数据,当然必须以可信任的用户比如icbacct用户登录后方可实现。
┌──────┐ 数据服务器名:acct_online
│ ONLINE 7.1 │ 主机名:acct_qz
│ (内嵌Star) │ (服务器)
└┬───┬─┘ DDN,TCP/IP
┌───┘ └─────┐
┌──┴──┐ ┌──┴──┐
│ONLINE 5.0│主机名:acct_ha│ONLINE 5.0│主机名:acct_xx
│ I-Net │(客户机1) │ I-Net │(客户机2)
└─────┘ └─────┘
图1 客户服务器结构的网络拓扑图
比如一台服务器和两台客户机以TCP/IP网络连接在一起(图1),在服务器上建立数据库服务器cct_online,在$INFORMIXDIR/etc/sqlhosts文件中命名。在/etc/services文件中定义了服务名sqlexec及该服务占用的端口号和所采用的协议类型,如2000/tcp 表示占用2000号端口,协议类型为TCP。下面以服务器主机acct_qz为例来加以说明:
① 文件/etc/hosts:
#net address hostname host alias
10.168.100.3 acct_qz host1_alias
10.168.106.1 acct_ha host2_alias
10.168.107.1 acct_xx host3_alias
② 文件$INFORMIXDIR/etc/sqlhosts:
#dbservername nettype hostname servicename
acct_online onsoctcp acct_qz sqlexec
③ 文件/etc/services:
#service_name port#/procotol aliases
sqlexec 2000/tcp
sqlrmtlitcp程序与普通的客户机通信软件一样要通过服务sqlexec对应的端口号2000与服务器建立连接,所以端口号2000必须保证全局一致。客户机acct_ha和acct_xx上的这三个文件内容基本上要与服务器acct_qz上的三个文件一样。
2 在单机上运行客户服务器应用程序
由于惠安县支行最近采用市行推广的新的基于INFORMIX-OnLine客户服务器结构的会计应用程序,笔者出于维护工作的需要,有必要学习和熟悉这一新的应用程序,但苦于本单位还没有另外一套备用的客户服务器网络运行环境而无法实现。后来经笔者研究终于找到了一种巧妙的方法,可以将整套应用程序安装在一台机器上运行。另外在开发和研究时将客户服务器结构转为在单机上运行也是很有用的,在不具备客户服务器网络条件时同样也能够在单机上编写客户服务器结构的应用程序。正是因为数据库名可以支持两种格式从而使得单机运行成为可能。单机上运行SCO UNIX 3.2和OnLine 5.0,而且不必安装Net或Star。
2.1 建立数据库服务器
在单机上建立与服务器主机名字(acct_qz)一样的数据库服务器:acct_qz,这一点最重要了,是整个应用程序能够在单机上运行的关键。在单机上也要建立icbacct用户,其.profile文件必须输出变量:INFORMIXSERVER=acct_qz。
2.2 建立足够大的数据库空间文件和逻辑日志
修改tbconfig的几个参数:
ROOTPATH /dev/online1
ROOTSIZE 50000
LOGFILES 20
LOGSIZE 500
LTAPEDEV /dev/null
DBSERVERNAME acct_qz
将系统参数SHMMAX改为1048576,SHMMNI改为500,然后在root用户下运行:
# cat /dev/null /dev/online1
# chown icbacct /dev/online1
# chgrp informix /dev/online1
最后在icbacct用户下运行:tbinit -i建立数据库空间。
2.3 用ESQL/C生成存储过程
因为OnLine 5.0不能用isql直接使用SQL语句生成存储过程,所以一般要使用ESQL/C编写专门的C语言程序来增加或更换一个存储过程。
$drop procedure tb2;
$create procedure from "/usr/icbacct/proc/tb2.sql";
上面两条语句先删除已存在的存储过程tb2,然后再生成新的存储过程,否则无法生成。因为我们不可能为每一个存储过程都编写一个专用的C语言程序,但由于drop语句不能带可变参数运行,比如不支持下面这样的语句:$drop procedure $spname;,所以只好编写一个删除全部存储过程的程序和一个生成全部存储过程的程序,每次要更换一个存储过程都不得不删除全部存储过程然后再重新生成,笔者认为这是一种不好的方法。为此笔者编写了一个C语言程序用来增加或更换一个存储过程,可以带命令行参数运行。方法是在客户机或单机上直接运行aproc ,就可增加或更换服务器上的一个存储过程。如tb2u.sql生成存储过程tb2,则命令行如下:aproc tb2 tb2u。SQL文件是生成存储过程的*.sql文件,文件名可以省略后缀“.sql”且固定存放在某一目录中。
其中的sqlcmdtxt结构来源于esql编译时产生的aproc.c中间文件,这也给我们一个启示,在C语言中间程序中有不少值得学习和研究的东西,当遇到用ESQL/C难以解决的问题时不妨看看C语言中间程序,或许会受到启发。比如打开数据库的语句是:
$datebase icbdb@acct_qz;
也可直接写成:_iqdbase("icbdb@acct_qz",0);,这就意味着当客户机程序要对多台服务器上的数据库进行操作时可以灵活地选择数据库名。单机上的ESQL/C程序也可用下面语句打开数据库:$database icbdb@acct_qz;,这时使用的就是数据库名的第二种格式,当程序在客户机上运行时又成了第一种格式,此时acct_qz就不再是数据库服务器的名字(DBSERVERNAME)而是服务器的主机名。源程序aproc.ec如下:
#include
$include sqlca;
$include sqlda;
$char s_sql[50],s_spname[50];
static char *sqlcmdtxt[ ]={
" drop procedure tb2",0
};
static _SQSTMT _SQ0={0};
main(argc,argv)
char *argv[ ];
{
$database icbdb@acct_qz;
$begin work;
sprintf(s_spname,"/usr/icbacct/proc/%s.sql",argv[2]);
sprintf(s_sql," drop procedure %s",argv[1]);
strcpy(sqlcmdtxt[0],s_sql);
_iqstmnt(&_SQ0,sqlcmdtxt,0,(char *)0,(char *)0);
$create procedure from $s_procname;
$commit work;
$close database;
}
OnLine 7.1将存储过程以记录的方式存放在系统数据库sysmasters中,OnLine 5.0则不存在系统数据库,但是却有二十几个以sys开头的系统表,所以也可以用isql查询存储过程,方法是选择Form/Generate,直接输入表名sysprocbody和sysprocedures,存储过程也是以记录的形式存放在这两个表中。
2.4 数据的倒出和倒入
既然要在单机上运行应用程序,所以有必要将服务器上的数据库的数据倒出并倒入到在单机上的数据库中。在客户机上运行"dbexport icbdb@acct_qz"命令倒出服务器上的数据库的数据,成功运行后将会在当前目录下生成dbexport.out文件和icbdb@acct_qz.exp目录,其中dbexport.out包含生成数据库和数据库表以及建立所有索引的SQL语句,倒出的数据存放在icbdb@acct_qz.exp目录下。将文件dbexport.out和icbdb@acct_qz.exp目录压缩后拷到单机上