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目錄壓縮後拷到單機上