分享

Informix 高级培训教材...

 昵称90415 2009-02-24
Informix 高级培训教材
 
作者:qaz1wsx  出处:Unix爱好者家园unix-cd.com  更新时间: 2004年07月22日 
 
 目录 
1. ONLINE5 与ONLINE7 的比较.............................................................................. 4 
1.1. 系统体系结构的差别................................................................................... 4 
1.2. 系统性能的差别....................................................................................... 4 
1.3. 系统可靠性的差别..................................................................................... 4 1.4. 命令的差别.......................................................................................... 5
2. ONLINE7 的配置及性能调整............................................................................... 5 
2.1. 确定系统性能的目标................................................................................... 5 
2.2. 系统性能监测和调整的基本方法.......................................................................... 6 
2.3. 影响性能的配置参数................................................................................... 6 
2.3.1. 影响性能的CPU 参数................................................................................. 6
2.3.2. 影响性能的内存参数................................................................................. 8 
2.3.3. 影响性能的I/O 的参数.............................................................................. 10 
2.4. 操作系统上的性能监控................................................................................ 12
2.4.1. Sar ............................................................................................. 12
2.4.2. iostat .......................................................................................... 13 
2.4.3. vmstat ........................................................................................... 14
3. 程序及数据的性能调整................................................................................... 16
3.1. 索引................................................................................................ 16
3.2. 关于with hold ...................................................................................... 16 
3.3. 关于事物............................................................................................. 17
3.4. 关于语句写法......................................................................................... 18
3.5. 关于使用put , execute 来代替insert 提高效率.......................................................... 20 
3.6. 使用隔离级别(isolation)............................................................................ 20 
3.7. 使用优化器(update statistics)..................................................................... 21
3.8. 使用复合索引........................................................................................ 22 
4. INformIX 数据库数据复制(CDR)......................................................................... 23 
4.1. 基本概念............................................................................................ 23
4.1.1. 数据复制类型:同步、异步........................................................................... 23
4.1.2. 复制机制:基于触发器和基于日志...................................................................... 23
4.1.3. CDR 的局限性...................................................................................... 24
4.1.4. CDR 如何实现...................................................................................... 24
4.2. CDR 配置实例......................................................................................... 25
4.2.1. 系统环境准备....................................................................................... 25
4.2.2. 确定复制环境....................................................................................... 26 
4.2.3. 建立picc21 和ibm500 的数据库之间的互访.............................................................. 26
4.2.4. 定义replicate server ............................................................................. 26
4.2.5. 确定复制服务器已建立............................................................................... 27
4.2.6. 增加连接成员: .................................................................................... 27
4.2.7. 确定成员已连接..................................................................................... 27
4.2.8. 定义replicate..................................................................................... 28
4.2.9. 确定replicate 建立................................................................................ 28
4.2.10. 启动replicate.................................................................................... 28
4.2.11. 确定replicate 已启动............................................................................. 29 
4.2.12. 关闭replicate.................................................................................... 29
4.2.13. 维护CDR.......................................................................................... 29
4.2.14. 监控CDR 工作情况................................................................................. 30 
4.2.15. CDR 出错处理.................................................................................... 30 
4.3. CDR 的时间同步....................................................................................... 30 

1. ONLINE5 与ONLINE7 的比较
1.1. 系统体系结构的差别
   ONLINE5 的内部处理结构是一对一的单线索的结构,每个用户对应一个数据库服务器进程,数据库服务器进程负责响应客户的数据请求,而数据库内部的协调处理由ONLINE 守护进程负责,数据库服务器进程和ONLINE 守护进程间相互独立。
   ONLINE7 采用的是先进的多线索的体系结构,多线索结构是核核心层的,客户应用进程和数据库服务器进程(VP)之间是多对多的关系,即一个客户应用进程可以有多个数据库服务器进程服务,反之,一个数据库服务器进程也可以为多个客户应用进程服务。
   ONLINE7 的优点是:充分利用CPU 的并发处理能力,而且数据库服务器进程的数目不是随着用户进程的增加而增加,减轻了系统的负荷。
   ONLINE5 中,客户应用进程和数据库服务器进程之间的通信是通过UNIX 管道实现的,数据库服务器进程间通讯是通过共享内存完成的。如果通过网络连接必须使用INformIX-STAR 这个产品。而ONLINE7 集成了INformIX-STAR,户应用和服务器之间的通讯即可以是共享内存方式也可以通过TCP/IP 的SOCKET 或TLI 实现,同时还支持了IPX/SPX 协议。 e[Q$J
1.2. 系统性能的差别 S
   ONLINE5 不能在联机方式下改变共享内存的大小和数据库服务器的个数,而ONLINE7 可以在联机的方式增加共享内存和增加虚拟处理器的个数,这样就达到了系统的动态可伸缩的特性。
   ONLINE7 因使用了多线索体系结构,一个查询可以使用多个线索,因此很好的支持了并行查询的功能(PDQ)。ONLINE7 还增加了对数据分割的支持。
1.3. 系统可靠性的差别
ONLINE7 增加了数据复制的功能(CDR)。
ONLINE7 在数据备份和恢复功能都有所增强,备份可以并行创建。只要rootdbs没有损坏,任何一个chunk 的损坏不影响整个ONLINE 的运行。ONLINE 启动时的快速恢复功能也使用多线索并行处理。
Informix 高级培训教材(内部) []A4H
5 ©91Talk论坛 -- 张扬你的个性,IT技术、时尚、娱乐.. 就要自由,就要TALK!  n3DSlkz
1.4. 命令的差别
ONLINE5 的命令都以tb 开头如:tbinit, tbmode,tbstat, tbtape
ONLINE7 的命令都以on 开头如:oninit, onmode,onstat, ontape 
另外,在ONLINE 配置方面ONLINE7 多了许多参数,这部分在ONLINE 配置部分介绍。
2. ONLINE7 的配置及性能调整 
   这部分讨论的是INformIX ONLINE 数据库服务器的性能监测和调整。性能监测和调整的研究和实践是很广泛的。这里只讨论ONLINE 数据库管理的日常维护的问题和方法。人们一直在讨论如何提高数据库的性能,数据如何存储、如何读取、如何配置参数才使你的应用得到更好的性能。例如:当要优化一个系统时,为一个有1000 用户并都执行短小简单的事物的系统,和为一个只有很少用户但执行很长且复杂的事物的系统的参数配置是完全不一样的。我们从以下几个方面阐述:
² 监控系统资源并评价系统的性能
² 数据库活动对系统性能评价的影响
² 用online 提供的工具来监控和调整系统性能
² 从以下几方面消除系统性能的瓶颈:
1. 平衡系统资源的负载
2. 调整online 的参数
3. 调整数据的布局
4. 为关键查询分配资源
适当平衡系统负载往往可以改善系统性能。有时性能改善是变化的,且往往使用单一的负载均衡的方法不能完全满足要求,下面从更广的范围对此进行讨论:
1. 修改应用程序,以便其能更好的利用操作系统和数据库的资源
2. 系统性能没有被充分利用
3. 网络的性能影响了C/S 结构的应用性能
2.1. 确定系统性能的目标确定系统性能目标时考虑的问题:
1. 要获得最大的交易吞吐量,还是最快的响应时间,或者是两者的混合。
2. 网络对性能的影响
3. 希望的最大用户数
4. 你的配置是否受内存、磁盘和CPU 资源的限制Informix 高级培训教材(内部) 

2.2. 系统性能监测和调整的基本方法
   系统的性能是否好是个模糊的概念,不太容易说清楚,比如用户会说有时系统很慢,有时一个交易不知道为什么不能完成等等,这就需要透过表面现象分析系统性能问题的真正瓶颈。我们建议通过反复多次的评价、调整的方法来接近您所要求的性能目标。如果反复的经过下面提供的步骤的调整都无法满足您对性能的要求,则很可能是您的硬件资源受到限制,或应用程序编码不当引起的问题。
ONLINE性能优化步骤
1. 确定您的性能目标.
2. 获得资源利用率和数据库活动的数据
3. 确定性能问题的症状:不均衡的CPU、内存和磁盘的利用率。
4. 调整操作系统的参数。
5. 调整ONLINE的参数。
6. 优化chunk 和dbspace 的配置, 包括日志、排序空间、临时表和排序文件的存放位置。
7. 优化表的存放位置、extent大小和分段处理。
8. 改善索引. 
9. 优化后台I/O活动,包括logging, check-points,和page cleaning. 
10. 规划备份和批处理业务的时间
11. 优化数据库应用的执行。
12. 重复2-11 部。
2.3. 影响性能的配置参数
   影响性能的参数包括操作系统的参数和ONLINE 的参数。在进行参数调整前应该对当前参数的性能进行评估。一般改变操作系统参数需要重新启动机器,改变ONLINE 的参数需要重新启动ONLINE。
2.3.1. 影响性能的CPU 参数
1.操作系统的参数:
1.信号量(SEMMNS ) 
SEMMNS = init_vps + added_vps + (2 * shmem_users)+concurrent_utils 
2.同时打开文件数(NFILES)
NFILES = (chunks * NUMAIOVPS) + NUMCPUVPS + net_connections 
2.ONLINE的相关参数:
NUMCPUVPS:初始分配的CPU VPs的个数,在单处理器的主机中此值建议用1,再多处理器的主机中此值不应大于物理CPU的个数,建议使用比物理处理器少1。此值可以通过onmode -p命令动态增加。
   CPU VPs的个数将决定在一个查询中扫描线索(Scan Threads)的个数。当扫描线索数的整数倍时查询会获得最好的性能。onstat -g ath命令监控每个CPU VP的扫描线索数,onstat -g ses命令监控某个具体会话。
SINGLE_CPU_VP:当CPU VPs值等于1时,此值也设置为1,否则为1。当此值为1时,NUMCPUVPS必须设置为1,否则ONLINE会报错。
MULTIPROCESSOR:当CPU VPs值大于1时,此值也设置为1,否则为0。 
NOAGE:为ONLINE CPU VP设置关闭处理器优先级老化的开关(需要OS支持),1为关闭。AFF_NPROCS:CPU绑定功能,就是可以通过CPU绑定来为处理器分配不同的任务。绑定几个CPU。
AFF_SPROC:从第几个CPU开始绑。
NUMAIOVPS:说明使用几个AIO VPs。如果OS不支持核心异步IO (KAIO)的话,ONLINE使用AIO管理所有数据库I/O请求。AIO Vps的个数依赖于你配置了多少磁盘。如果系统不支持KAIO的话,建议为每个chunk分配一个AIO VPS。还有一个分配AIO VPs的标准是看I/O请求队列的长度是否足够短。onstat -g ioq 命令可以监控待AIO VPs 处理的I/O请求队列的长度。
尽量多的分配AIO VPs是不会对系统有何副作用,可以通过onmde -p动态增加AIO的个数,但不能动态的减少。
OPTCOMPIND:该参数帮助优化器为应用选择一个最适合的存取方式。如果该值为0,优化器首先选择已存在的索引既是顺序扫描速度更快。当该值为0,并且隔离级别设置为重复读模式,优化器适用嵌套循环连接的方式。当该值为2(缺省),优化器选择基于消耗评估的连接方法,即使表扫描引起整个表被临时锁住。用户可以通过设置环境变量改变该值。
MAX_PDQPRIORITY:该值限制一个查询可以占用的PDQ资源的百分比。
DS_MAX_QUERIES:描述同事的最大决策支持查询的个数。ONLINE通过该值和DS_TOTAL_MEMORY: 决定为一个查询分配多少内存。
DS_MAX_SCANS:该值限制了PDQ的扫描线索的个数。该值避免PDQ引起的扫描线索被过度使用。
分配给一个查询的扫描线索数是通过下面的公式计算的:
scan_threads = min (nfrags, (DS_MAX_SCANS * pdqpriority / 100*MAX_PDQPRIORITY / 100) )
减少扫描线索数可以提高几个大查询同时运行时的响应。
NETTYPE:为每个连接类型配置轮训线索。一般情况每个DBSERVER 对应一个连接类型。轮训线索可以定义两种类型VP: CPU 和NET。建议只使用一个CPU 类型的轮训线索,其它的给NET 类型的轮训线索,总的轮训线索数不能大于努NUMCPUVPS。尽管训线索理论上可以支持1024 个连接,但单CPU 主机每个轮训线索支持300 个连接比较好,而多CPU 主机每个轮训线索支持350 个连接比较好。该值为定义缺省是一个CPU 轮训线索,每个轮训线索支持50 个连接。适当的增加轮训线索可以提高性能。注:ipcshm 方式的连接是需要占用信号量资源的。 
onstat -g glo 
当前运行的各个虚拟处理器(VP)已占用的CPU 资源。可以通过间隔1 分钟时间两次执行该命令, 将两次结果9 相减,如果结果接近60 秒说明CPU 很忙。
onstat -g rea 
监控等待运行的线索,如果列出线索较多说明CPU 处理能力不足。可以考虑增加CPU VP 的个数。
2.3.2. 影响性能的内存参数
这部分讨论影响性能的内存参数,包括OS 和ONLINE 的参数配置,你必须考虑如何均衡的使用有限的内存资源。
当OS 分配一块共享内存是我们把它叫做段(segment), ONLINE 在用这块共享内存段时我们又把它叫做区(portion)。ONLINE 根据需要把共享内存分成了3 个区分别是: 
²  驻留内存区:这部分时静态的,在ONLINE 初始化时分配。它是由以下几个参数组成的:
BUFFERS:通过下面的公式可以计算出buffer所占内存
buffer_value = (BUFFERS * pagesize) + (BUFFERS * 254)
LOCKS:通过下面的公式可以计算出LOCK所占内存
locks_value = LOCKS * 44 
LOGBUFF:通过下面的公式可以计算出逻辑日志buffer所占内存
logbuff_value = LOGBUFF * 1024 * 3 
PHYSBUFF:通过下面的公式可以计算出物理日志buffer 所占内存
physbuff_value = PHYSBUFF * 1024 * 2 
驻留内存区的大小是按下面的公式计算的:
rsegsize = (buffer_value + locks_value + logbuff_value+ cphysbuff_value + 51,200) / 1024
另外, RESIDENT 设为1 时这部分被强制驻留物理内存而不会被换出( OS 要支持)。
²  虚拟内存区:这部分时动态增长的,但在初始化是也应分配个适当的值。它是由以下几部分组成的:
用于大的读写操作的大缓冲区
排序池 
活动线程控制块、栈、堆 
用户对话数据 
数据字典高速缓存和存储过程
用于网络接口信息的全局池 
初始的区大小由SHMVIRTSIZE 参数决定,增加的区大小由SHMADD 参数决定。
根据一般经验,每个用户要占100K~500K 的虚拟内存区的空间,如果用了数据分割应该再加4M。可以用onstat -g mem 命令共享内存区的大小
²  消息内存区:这部分是静态的,在ONLINE 初始化时分配。它包括共享内存通讯接口的消息缓冲区。它的大小依赖与你允许的连接用户数。它的大小可由下面的公式计算出Informix 
msegsize = (10,531 * ipcshm_conn + 50,000)/1024 
与内存有关的ONLINE 参数 
SHMVIRTSIZE:决定虚拟内存区的初始区大小。当虚拟内存区不够用时ONLINE会自动增加一个新的区,但这会消耗ONLINE的处理资源。因此,该值应该尽可能的,一般先下面两种情况中大的一种:
8,000 或connection* 350 
SHMADD:决定ONLINE动态增加的虚拟内存区的大小。虚拟内存区的增加会消耗CPU的资源。它也应尽可能的大,但当内存方生很多的换出的情况,就应减少了。建议按下表进行设置 
===========================================
Memory Size SHMADD value
256 megabytes or less 8,192 kilobytes (the default)
Between 257 and 512 megabytes 16,384 kilobytes
Larger than 512 megabytes 32,768 kilobytes 
===========================================
可以用onstat -g seg 命令监控ONLINE共享内存区的使用情况。
SHMTOTAL:限制ONLINE最多使用的共享内存的大小。如果是0,根据实际情况动态增加,除非有特殊情况,如大量内存被换出,一般都设置为0。
BUFFERS:设置ONLINE使用的数据缓冲区的多少。该部分是驻留内存区,用户数据在内存中的高速缓冲。更多的BUFFER可以带来更多的曾经访问过的数据驻留在内存中。该值对数据库I/O和交易吞吐量都是非常重要的。但过多的分配BUFFER也会造成内存资源的浪费而影响其他部分对内存的使用。建议BUFFER占用的内存是实际内存的20%~25%之间。用onstat -p 命令看读写cache的大小,如果过低应该增加该值。 配置原则是物理内存的20%~30%。在系统没用页交换发生的情况下,尽量多的增加buffer。用onstat -p 命令察看读Cached 在95%以上,写Cached在85%以上说明BUFFERS 值较合理,同时结合vmstat 命令观察交换区的使用情况。
LOCKS: 如果onstat -p 中lockwaits 值较大应适当增加locks 数。有个有用的命令: onmode -F 方法系统空闲的内存,并可以将该命令加到系统的crontab 中定期执行。
RESIDENT: 确定驻留内存区是否被被强制驻留在物理内存中,而不会被换出(OS 要支持)。驻留内存区还包括可LRU 对列,LRU 与数据库的读写操作有关。该值建议设为1,如OS 不支持将报错并被忽略。
STACKSIZE: 确定为每个线程分配多少栈空间。该部分空间是在虚拟内存区中分配的。用如下公式计算总的栈大小: 
stacktotal = STACKSIZE * avg_no_of_threads
LOCKS:确定同时可以打开的最大的锁的数目。绝对最大值是8M,每个LOCK占用44字节(在驻留区)。可以通过下图来评估一条SQL语句可能占用锁的个数:
LOGBUFF:确定逻辑日志的缓冲区的空间大小。它的大小决定了逻辑日志被刷新的磁盘上的频度。 
PHYSBUFF:确定物理日志的缓冲区的空间大小。它的大小决定了物理日志被刷新的磁盘上的频度。
DS_TOTAL_MEMORY: 确定一个查询最多可获得的共享内存百分比。一般,在一个OLTP 系统中该值为:20%~50%之间。如果是一个DDS 系统中该值为:50%~80% 之间,甚至90% 。当该值未赋则ONLINE 按如下公式计算: 
min_ds_total_memory = NUMCPUVPS * 2 * 128Kb
2.3.3. 影响性能的I/O 的参数
CHUNK 和DBSPACES 的配置
在整个I/O 过程中磁盘是最为缓慢的一个环节,因此如何安排好磁盘空间的使用也使I/O 性能的关键。
在创建CHUNK 时建议将一个完整的分区分配个CHUNK,避免offset 计算错误引起的数据访问失败。 
在5.0 以前的版本建议一个DBSPACES 使用都个CHUNK 来提高性能,但从7.0 以后对此不在要求,反而是最好一个DBSPACES 用一个CHUNK,这样便于作数据分割。
ONLINE 在缺省情况将临时表建在rootdbs 中,建议使用DBSPACETEMP 参数建立temp dbspace, 用于临时表的存放。
设置预读的参数
RA_PAGES: 确定ONLINE预读的页数,
RA_THRESHOLD:ONLINE 响应I/O 请求的指针
用下面的计算公式:
RA_PAGES = (BUFFERS * bp_fract) / (2 * large_queries) + 2
RA_THRESHOLD = (BUFFERS * bp_fract) / (2 * large_queries) - 2 
配置后台I/O
后台I/O 不能直接服务于SQL 请求。后台I/O 主要是维护数据一致性。后台I/O带来高速的I/O 同时消耗CPU 资源,同时会与交易竞争系统资源。如果后台I/O 过多会影响应用的性能。下面是一些后台I/O:
Checkpoints
Logging 
Page cleaning 
Backup and restore 
Rollback and recovery 
Data replication 
Checkpoints、Logging、Page cleaning 是数据库维护数据一致性所必需的后台I/O。相对后台I/O,前台I/O 的效率比较差,因此尽量避免前台I/O。可以通过增加Page Cleaning数或减少触发Page Cleaning 来减少前台I/O。用onstat -F 命令可以监控前台I/O 的频率。 
影响后台I/O 的参数 
CKPTINTVL:设置checkpoint的时间间隔,onstat -m可以监控checkpoint的时间。当物理日志达到75%时也发生checkpoint,
LOGSIZE 
LOGSIZE 
LOGFILES 
LOGSMAX 
PHYSFILE 
PHYSFILE
影响日志的参数 
LOGBUFF 
PHYSBUFF
LTXHWM 
LTXEHWM 
影响Page Cleaning 的参数
CLEANERS:清页线索的个数,建议每个磁盘使用一个清页线索。
LRUS 有更多的LRU就会有更多的Page Cleaning,用onstat -R命令监控脏页的比例 
LRU_MAX_DIRTY:LRU的最大脏读比例
LRU_MIN_DIRTY:LRU的最小脏读比例
RA_PAGES 6
RA_THRESHOLD 

三种写的比较
1. 前台写:由sqlexec 亲自刷新,前台写效率最低尽量避免。
2. LRU 写:它是由LRU_MAX_DIRTY 和LRU_MIN_DIRTY 决定刷新的频率,并且这种刷新操作是不彻底的,但有个好处是在刷新时不会终止用户线索的操作。
3. Chunk 写:这种写实最彻底并且效率最高,但在写的时候所有用户线索不能进入临界区,因此检查点会延迟用户的响应时间。
通过onstat -F 可以观察以上三种写的使用情况。可以通过改变LRU_MAX_DIRTY 和LRU_MIN_DIRTY 及CKPTINTVL 的值调整写的方式。
2.4. 操作系统上的性能监控 
IBM RS6000 系列小型机上的AIX 4.3.3 操作系统提供了一些列的系统性能分析工具,这些工具主要以命令行方式执行,平时我们常用的主要有3 个命令sar、iostat 和vmstat, 它们是从不同侧面反映当前系统的性能,sar 是针对系统整体性能的反映,iostat 是针对系统I/O 性能的反映,vmstat 是针对系统内存和CPU 使用状况的反映。下面我们一一进行分析说明。 
2.4.1. Sar
sar 是UNIX 系统提供的一个标准的系统性能报告工具,它有一些列的参数,一部分参数因UNIX 系统的不同而不同。我们主要用sar 命令来观察系统的整体性能。
使用方法: sar 60 60
说明:第一个数字代表采样的时间间隔,这里定为60 秒 
第二个数字代表采样的次数,这里定为60 次
这样我们就能看到系统从现在开始一个小时内的系统性能报告(1 分钟采样1 次)
输出结果:
AIX s7a 3 4 000946594C00 11/23/01 
13:55:53 %usr %sys %wio %idle 
13:55:54 14 2 84 0 
13:56:54 21 4 63 12 
13:57:54 24 2 68 6
13:58:54 12 1 86 0 
13:59:54 10 2 86 2 
14:00:54 14 2 64 20 
14:01:54 10 1 11 79
14:02:54 18 1 56 26 
14:03:54 14 2 74 10 
14:04:54 9 2 76 13 
14:05:54 10 2 77 10 
14:06:54 11 4 83 2 
14:07:54 12 1 72 16 
14:08:54 6 2 77 16 
t14:09:54 23 3 63 11 
14:10:54 26 2 61 11
14:11:54 10 2 67 21 
14:12:54 32 2 65 0 
14:13:54 36 1 52 10 
14:14:54 31 3 9 57 
14:15:54 36 3 60 0 
14:16:54 35 3 56 6 
14:17:54 27 3 70 0
14:18:54 31 4 61 4 
14:19:54 34 1 54 11 
14:20:54 26 0 6 67 
14:21:54 0 0 0 100 
Average 20 2 60 17 
说明:标准sar 命令结果显示如图的五列内容
第一列:说明采样的系统时间 
%usr:用户进程占用整个系统CPU 的百分比
%sys:系统进程占用整个系统CPU 的百分比 
%wio:I/O 等待占用整个系统CPU 的百分比 
%idle:空闲占用整个系统CPU 的百分比 
其中%usr + %sys + %wio+ %idle=100% 
可以通过观察%idle 的值来确定当前整个系统的繁忙程度,该值越小说明系统 WH越繁忙。当%wio 值持续大于15%时说明系统的I/O 可能成为瓶颈。当%idle 值持续是零,并且%sys 值很高且大于%usr 的值,说明系统过多的使用交换区,即有可能内存不足。 
从以上观察系统性能的结果可以分析出,系统CPU 存在大量I/O 等待,即系统I/O 性能比较低,I/O 成为系统性能的瓶颈。
相对用户和系统本身占用的CPU 资源平均20%,因此,现有CPU 资源可以满足使用需要。
2.4.2. iostat D
iostat 是AIX 系统提供的一个系统I/O 性能报告工具。可以观察系统I/O 设备的吞吐率。
使用方法: iostat -d hdiskx 60 60 
说明:-d hdiskx 可以选择具体的磁盘 
第一个数字代表采样的时间间隔,这里定为60 秒 
第二个数字代表采样的次数,这里定为60 次
这样我们就能看到系统从现在开始一个小时内的系统性能报告(1 分钟采样1 次)
输出结果:
Disks: % tm_act Kbps tps Kb_read Kb_wrtn 

hdisk2 98.0 4808.0 267.0 4804 4 
hdisk2 95.0 5164.0 301.0 5164 0
hdisk2 79.8 4137.7 266.3 4148 0
hdisk2 64.0 3220.0 214.0 3220 0 
hdisk2 25.0 1112.0 78.0 1112 0 
hdisk2 34.0 1692.0 116.0 1692 0 
hdisk2 71.0 3536.0 236.0 3496 40 
hdisk2 67.0 3792.0 251.0 3792 0 
hdisk2 80.0 3416.0 238.0 3416 0 
hdisk2 74.0 3936.0 265.0 3936 0 
hdisk2 72.0 3544.0 238.0 3544 0
hdisk2 79.0 3176.0 223.0 3140 36 
hdisk2 74.0 2912.0 197.0 2908 4 
hdisk2 69.0 3460.0 227.0 3460 0 
hdisk2 70.0 3348.0 230.0 3344 4 
hdisk2 68.0 3944.0 258.0 3944 0 
hdisk2 97.0 1372.0 139.0 552 820 
hdisk2 99.8 638.4 111.7 64 576 
hdisk2 100.0 536.0 115.0 84 452 
hdisk2 100.0 524.0 103.0 84 440 
hdisk2 100.0 536.0 101.0 148 388 
hdisk2 100.0 660.0 127.0 148 512 
hdisk2 100.0 516.0 104.0 132 384 
说明:iostat 命令结果显示如图的六列内容
Disks: 所观察的磁盘名称 
% tm_act :设备使用率的百分比 
Kbps :设备每秒种读、写的KB 数 
tps :设备每秒种读、写请求的次数 
Kb_read :设备每秒种读的KB 数 
Kb_wrtn :设备每秒种写的KB 数
从以上观察系统性能的结果可以分析出,用作数据库的磁盘hdisk2 I/O 非常繁忙,最高时达到了100%,磁盘读写率最高5M/S, 平均3M/S, 可以判断磁盘读写能力较差,这主要有两方面的原因:现有磁盘阵列的磁盘本身读写慢( 7200 转); RAID卡没有读cache。
2.4.3. vmstat 
vmstat 是AIX 系统提供的一个综合性观察系统性能的工具,包括观察系统核心线
程、内存、交换区、系统调用及CPU 的运行情况。
使用方法:vmstat 60 60 
说明:第一个数字代表采样的时间间隔,这里定为60 秒 
第二个数字代表采样的次数,这里定为60 次 
这样我们就能看到系统从现在开始一个小时内的系统性能报告(1 分钟采样1 次)
输出结果:
kthr memory page faults cpu 
----- ----------- ------------------------ ------------ -----------
r b avm fre re pi po fr sr cy in sy cs us sy id wa
0 1 161419 645 0 0 0 0 0 0 1044 1973 1084 20 2 0 78 
1 1 161419 645 0 0 0 0 0 0 1024 2106 1104 24 2 2 72 
1 1 161615 430 0 0 0 0 0 0 1016 4244 1009 21 2 0 77 
1 1 161099 1000 0 0 0 0 0 0 1051 2517 1241 17 2 0 82 
0 1 160957 1161 0 0 0 0 0 0 988 2367 1225 16 2 0 82
1 1 160424 1762 0 0 0 0 0 0 967 3263 1173 45 4 0 51
2 1 160424 1762 0 0 0 0 0 0 1008 1920 1133 23 2 1 74
0 1 160192 2034 0 0 0 0 0 0 990 2666 1295 18 2 3 78 
0 1 160329 1878 0 0 0 0 0 0 958 4974 1444 14 2 3 82 
0 1 160449 1739 0 0 0 0 0 0 1053 4875 1288 10 2 4 84 
0 1 160454 1733 0 0 0 0 0 0 1025 4315 2830 30 4 0 66 
1 1 160455 1732 0 0 0 0 0 0 1042 2824 1741 13 2 1 84 
0 1 160456 1731 0 0 0 0 0 0 997 2207 1342 10 3 1 87 
0 1 160633 1542 0 0 0 0 0 0 1026 4433 1295 12 2 1 86 
0 1 160543 1626 0 0 0 0 0 0 1039 5321 1412 13 2 1 83 
1 1 159998 2221 0 0 0 0 0 0 964 3357 1499 22 3 3 72 
1 1 159876 2362 0 0 0 0 0 0 1015 2625 1423 13 1 2 84 
1 1 159876 2361 0 0 0 0 0 0 947 2150 1288 12 2 2 84
1 1 159879 2357 0 0 0 0 0 0 991 2058 1184 9 2 2 87
0 1 159879 2357 0 0 0 0 0 0 996 2208 1309 21 1 2 76 
说明:
kthr r : 在运行队列中的核心线程的个数 
b : 在等待队列中的核心线程的个数
memory avm : 正在使用的内存的页数
fre : 空闲的内存的页数 
page re : 内存交换的总页数
pi : 内存交入的总页数
po : 内存交出的总页数 
fr : 空闲的交换页 
sr : 页交换算法扫描过的页数 
cy :页交换算法锁的循环数 
faults in :设备中断
sy : 系统调用
cs : 核心线程上下文切换 
cpu us : 用户进程占用的CPU 时间
sy : 系统进程占用的CPU 时间 
id : 系统空闲的CPU 时间 
wa: 系统I/O 等待的时间 
从以上观察系统性能的结果可以分析出,系统还没有用到交换区的空间,这说明现有内存可以满足现有应用运行的需求,但空闲内存数不多,在用户持续增长的情况下有可能导致内存不足,应考虑适当增加内存容量。
3. 程序及数据的性能调整 
3.1. 索引
   在数据库中,索引对效率的影响可以说是决定性的。所以,索引使用的好坏直接影响系统的效率。每一索引的建立都要根据系统的使用综合考虑,哪些语句使用最频繁,这些语句的where 条件是什么,对当前表的更新频率如何。在索引的建立过程中,能够建成unique 索引的,最好建成unique 索引,举例说明:假设在业务系统中,check_info 表是核保信息表,有保单号(bm_cert)字段,在投保单登录前,此字段无值。若将此字段置为空,则登录前的投保单的保单号(bm_cert)均为空,就不能建唯一索引。此时若改变策略,将投保单时的保单号置为投保单号,(投保单号与保单号不会重复),则bm_cert 字段就可建唯一索引,大大提高了连表查询速度。对唯一索引可根据需要建成聚类,语法如下:
create cluster index id_person on person(insure_nu);
alter index id_person to cluster 
alter index id_person to not cluster 
聚类使数据的物理存储顺序与索引一致,减少取数的读盘次数,从而提高效率。
3.2. 关于with hold
   在游标中,如果在循环体内使用了事物,该游标的声明必须使用with hold 。否则该游标在事物后会被关闭。为此,可能习惯在声明游标时加上with hold,不管内部是否有事物。这种做法对单处理器机器可能没什么影响,但对多处理器机器就有影响了。 因为使用with hold 后,就不能使用并行查询。也就是说,用了with hold 后,pdq 不能起作用。因此,对于游标内未使用事物的,建议最好不要使用with hold。
3.3. 关于隔离级别
隔离级别设成脏读,可提高查询速度。若对某表查询,而该表的更新频率较高,这时在查询前设置set isolation to dirty read 可使查询速度大大提高。但要注意脏数据。有两种情况可以这样使用:
(1) 不怕读到脏数据,有脏数据也没有关系。 3#.6S
(2) 确信读不到脏数据。例如,假设在业务系统中,对rtdz2(单证状态表)表的更新比较频繁,而且此表的记录数也比较多,在很多情况下又要对该表进行实时查询。在更新时要锁记录,那么查询只好set lock mode to wait ,这样查询速度将会受到很大影响。只好将隔离级别设成脏读。为了保证实时数据不是脏数据,那么我们必须确保一点:系统中所有对rtdz2 的更新的语句都在事物的最后一句。而业务系统中已经做到了这一点。事实证明,此处效率的提高是显著的。
3.4. 关于事物 
   事物的作用相信大家都明白,这里就不再说明了。但在使用事物的时候,为了尽量减少锁表时间,事物中的语句应尽量少。因此在begin work 内最好只有更新语句update, delete , insert 等。而一些预备工作如查询,计算等都应放在begin work 外。
3.5. 关于数据分割 
当某一表的数据量较大时,可考虑用数据分割的方式来提高效率。数据分割就是将某一表的数据根据一定的条件放入不同的dbspace ,若这些不同的dbspace 在不同的物理盘上效果会更好。数据分割的用法如下所示:
create table rta14

bm_cert char(15), 
bm_type char(6), 
bm_way char(1), 
je_pay decimal(12,2), 
rq_payto date,
rq_lqstart date, 
flag char(5), 
age_min smallint, 
age_max smallint,
lj_pay decimal(16,2) 

fragment by expression
((bm_cert <= '002999999999999' ) OR (bm_cert >= '990999999999999' ) ) in datadbs1 , 
((bm_cert > '002999999999999' ) AND (bm_cert <= '099999999999999' ) ) in datadbs2 , 
((bm_cert > '099999999999999' ) AND (bm_cert <= '599999999999999' ) ) in datadbs3 ,
((bm_cert > '599999999999999' ) AND (bm_cert < '990999999999999' ) ) in  datadbs4
extent size 38566 next size 3856 lock mode page;
3.6. 关于语句写法 
语句的效率与SQL 语句的写法有很大关系。在几种写法中选择一个合适的写法相当重要,有时效率会急剧提高。因此,在效率有问题的地方多检查自己语句的写法,有可能会取得重大突破。以下是一些实例:
(1).在保单表中查找“003”险种的“0101”区站的数据
select * from rta1 where bm_cert[1,7]=”0030101”
该语句运行前设置set explain on,运行后查看sqexplain.out 结果如下:
QUERY:
select * from rta1 
where bm_cert[1,7]="0030107" 
Estimated Cost: 1
Estimated # of Rows Returned: 1 
1) hsx.rta1: INDEX PATH 8
(1) Index Keys: bm_cert 
Lower Index Filter: hsx.rta1.bm_cert[1,7] = '0030107' 
显示的搜索路径为索引路径,但实际上效率很低。现改为如下写法:
select * from rta1 where bm_cert > = ”00301010000000000000” 
and bm_cert<=”00301019999999999999”
该语句运行前设置set explain on,运行后查看sqexplain.out 结果如下: 
QUERY: 
select * from rta1 where bm_cert >= "003010100000000" 
and bm_cert<=”00301019999999999999” 
Estimated Cost: 1
Estimated # of Rows Returned: 3
1) hsx.rta1: INDEX PATH 
(1) Index Keys: bm_cert 
Lower Index Filter: hsx.rta1.bm_cert >= '003010100000000' 
显示与第一个写法无明显差别,实际上第二种写法效率远远高于第一种。实际测试第一种写法的时间需要2 分41 秒而第二种写法的执行时间只需14 秒。 

因此, 程序中最好不要使用bm_cert[x,y]=”???” 这种形式, 而改为 bm_cert>=”???” 这种形式。
(2). 在程序中,我们经常做这样的工作,先判断表内是否有该条数据,如果有就 update 该条数据,否则就插入一条。一般都写成如下形式:
select .. from . where key=t_key 
if status=notfound then 
insert into .. 
else 
update .. 
end if 
实际上,写成如下形式效率更高 
update . where key=t_key 
if status=0 and sqlca.sqlerrd[3]=0 then 
insert into ..
end if 
因为当该条数据存在时,只做一次写操作。 
(3). 在应用系统中有这样一条SQL 语句。 
select print_name from validate_item 
where (acc_book_type = t_acc_book_type 
and acc_book_code = t_acc_book_code 
and (center_code = t_center_code or center_code=”000000”) 
and item_code = t_item_code 
and direction_idx = t_dir_idx_val1 
and direction_other = t_dir_oth_val1) 
( validate_item 表中acc_book_type , acc_book_code , center_code , item_code , direction_idx , direction_other 为唯一索引) 该语句的效率不高,改写为以下形式后效率得到了很大提高。在存储过程中,上面的写法此存储过程执行需用时1 分多钟,改为下面的写法后,用时仅需1 秒.
select print_name 
into t_str 
from validate_item 
where (acc_book_type = t_acc_book_type 
and acc_book_code = t_acc_book_code 
and center_code = t_center_code 
and item_code = t_item_code 
and direction_idx = t_dir_idx_val1
and direction_other = t_dir_oth_val1) 
or (acc_book_type = t_acc_book_type 
and acc_book_code = t_acc_book_code
and center_code = "000000" 
and item_code = t_item_code 
and direction_idx = t_dir_idx_val1 
and direction_other = t_dir_oth_val1); 
在SQL 语句中,where 条件中有or 的语句,where 条件尽量用大组合,而不要用小组合。 

3.7. 关于使用put , execute 来代替insert 提高效率在做数据转换或登录大批量数据时,用put 或execute 替代insert ,将使效率大幅度提高。因为在循环体内,减少了对insert 的语法检查及预处理的时间。 
Put 的用法如下:
let t_pre_1 = "insert into rta1 value"
"(?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?)" 
prepare pre_rta1_1 from t_pre_1
declare cur_ins_1 cursor for pre_rta1_1 
open cur_ins_1
循环体(while , for , foreach) 

put cur_ins_1 from p_rta1.* 

close cur_ins_1 
execute 的语法如下: 
let t_pre_1 = "insert into rta1 value"
"(?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?,?,?,?,?,?,?,"
"?,?,?,?)" 
prepare pre_rta1_1 from t_pre_1 
循环体(while , for , foreach)

execute pre_rta1_1 using p_rta1.* 

使用put 必须注意以下内容:
u put 语句必须在事物中。 
u put 语句执行完后,马上从库中select 不一定能取到数
3.8. 使用隔离级别(isolation) 
共有四种隔离级别 
Dirty read 
Commited read 
Cursor stability 
Repeatable read 
<一> dirty read 
可能读到未提交(commited)的记录,可能读到最后被回滚的记录,该记录是一个phantom。 在一些查询中,使用此隔离级别,可提高效率。因为不受其他进程锁表,锁记录的影响。 

<二> committed read
读到的数据均为提交后的数据。两个进程可同时update 同一条记录。(缺省的隔离级别)
<三> cursor stability 
当隔离级别设置为cursor stability 时,在某一游标内,当前记录不能被其他
的进程update,delete ,但游标内其他的记录可被其他进程update ,delete 。
<四> repeatable read 
当隔离级别设置为repeatable read 时,在某一游标内有两种情况
1. 该游标的where 子句有索引,则满足条件的所有记录均不能被其他进程 
update ,delete 。(该索引的搜索树的所有节点)
2. 该游标的where 子句不在索引上,则该表的所有记录均不能被其他进程 update,delete 。
所以,当使用repeatable read 时,最好有索引,否则相当于锁表,极大损害系统效率。 
3.9. 使用优化器(update statistics)
对表,存储过程的优化的语法如下: 
update statistics [low ] for procedure .. 
[ medium] for table tablename [colname] resolution percent . conf 
[high ]
优化使系统表的信息与实际一致,使搜索树的路径最优。 
同时,整理索引树。
例: 
1. update statistics for table 
2. update statistics for procedure 
3. update statistics for table rta1(bm_cert)
4. update statistics high for table rta1(bm_cert) resolution 0.5
5. update statistics medium for table rta1 resolution 0.5 0.89 
3.10. 使用复合索引 
建复合索引的原则:
1. 查询语句中不定的字段尽量放在复合索引的后面。 
如有查询语句select * from person where name=”王艳” sex=”0” and birthday >”1982/12/1” 
则索引建成如下形式效率最好。
Create index idx_person on person(name, ,birthday ,sex) 
而不要建成 
Create index idx_person on person(birthday,sex,name) 
2. 取值范围大,可能值多的尽量放在复合索引的前面。 
性别只有两种取值“男“”女“ ,最好放在最后。 
姓名可能值最多,最好放在最前,则索引为:
Create index idx_person on person(name,birthday,sex) 若与第一条有冲突,第一条优先。 
3. 有单独作为条件的,最好放在前面。
如果如下的sql 语句出现的频率较高 
select * from person where name >” “ 
或select * from person where name matches “ “ 
则name 字段最好放在索引的前面。 
复合索引的建立必须根据整个系统的sql 语句,均衡的考虑。
4. INformIX 数据库数据复制(CDR) 
4.1. 基本概念 
4.1.1. 数据复制类型:同步、异步
l  同步:源数据更新同时马上更新目标数据,系统使用2 步提交技术保证了数据的完整性。 
2 步提交要求目标主机和网络环境有较高的可靠性。即任何时候都是可用的。 
l  异步:目标数据的复制可以根据应用要求设定,但最终要同步所有的数据。在一般的开放系统中,异步方式更为常用,因为它忽略了主机和网络的性能,这往往是一些系统的致命问题。
异步复制又分为如下几种模式:
1) 主从模式:所有数据更新都是从原到目标,是单向数据复制。如图示:
2) 工作流模式:数据在服务器间一一流转,也是单向数据复制。如图示:
3) 任意更新模式:所有定义的数据库之间都互相具有读写权限,它的弊端是容易引起复制冲突,当然CDR 也提供了冲突解决规则。如图示:
4.1.2. 复制机制:基于触发器和基于日志 s5NT3uZ
l  触发器方式:这种将与系统竞争对数据库表读写的资源,对正常业务效率有较大影响。并且需要通过应用保证数据完整性。该种方式不可取。
l  日志方式:由于是采取捕获事物信息的方式,因此不会与系统竞争对数据库表读写资源,效率高。且由系统保持数据一致性、完整性。并有可集中管理的优势。 
4.1.3. CDR 的局限性
l  仅提供IDS 之间的复制 
l  不能与HDR 并行使用。 
l  复制的表不能用view 
l  一个数据库服务器只能参与一个复制服务
一旦建立了复制服务器:
l  不能用drop table;rename talbe; alter fragment 等SQL 
l  复制的表必须有primary key,且不能修改 
l  不能对字段增删改 
l  不能建立聚合索引 
4.1.4. CDR 如何实现 
l 复制过程主要包括4 个部分: 
1. 捕获事物 
CDR 使用基于日志的事物捕获机制获得事物信息。这种方式不会与正常事物竞争对表的存取,所以能获得较好的性能。CDR 读log 后加上标志,并将它传送到下一步,复制评估。
2. 复制评估 
CDR 要确定每一条记录的最后值及更新发生时间,以便决定是否进行复制。评估是并行处理的以保证较高性能。评估后CDR 将数据置于消息队列。 
3. 数据分发
消息队列存取方式可以保证所有数据都可以准确到达目标SERVER,它可以忽略主机或网络的状态。当网络发生故障数据存放在本地发送消息队列中,当网络恢复后消息队列再自动将数据分发。 
4. 数据同步 :
CDR 用同步处理保证数据能正确的复制到目标SERVER,当复制数据正确存储到目标SERVER 后,目标SERVER 向源SERVER 发送确认信息。
l  CDR 的几个组成部分:
1. 复制SERVER:由一个dbserver 组成,与成员SERVER 可以在不同主机或同一主机上。 
2. 复制对象:包括database table columns 还有一些option 如冲突解决规则和范围。 
3. 成员:目标dbserver database table columns  限制条件:必须有primary key 只能复制单表;不能使用Join 和subquery.
4. 全局目录:是管理复制功能的一系列table , 全局目录在每个dbserver 都有一份,可集中管理。 
l  复制规划 
1. 确定系统拓扑结构,并制作如“三.复制实例”中的表3-1,拓扑如图示:采用树型主从模式。 
2. 有关逻辑日志:逻辑日志的大小应至少容纳一次复制所复制的数据。
3. 有关消息队列:消息队列是一个dbspace,它的大小不仅与逻辑日志有关,而且与网
络中断期间所需缓冲的数据多少有关。(Onconfig 中定义)
4. 影子表:如果定义了冲突解决规则,就要定义影子表,其大小根据规则不同而不同,
如基于时间戳的冲突解决规则需要是复制表的2 倍。 
5. 假脱机目录:可以指定事物中断后数据暂存目录(缺省:/tmp)。
6. 复制线程个数:是个均衡值即要保证性能也不能浪费(onconfig 中定义)。 
7. 网络带宽: 
流量计算如公式:(#transactions per hour)*(#bytes)*(#sites)*130% 
8. 应用分析:估算每天大约有多少数据增删改,分析传送时间安排。
9.确定要复制的database 用的是unbuffer 方式的逻辑日志。
4.2. CDR 配置实例
4.2.1. 系统环境准备 
1.数据复制源主机:IBM 370 SCO 5.0.5 IDS 7.31.UC2 CBPS 7 
2.数据复制目的主机:IBM 250 SCO 5.0.5 IDS 7.31.UC2 
3.检查逻辑日志(logical log)的大小 
4.建立发送、接受队列dbspace 
5.确定参与复制的Informix Server、database 及table 
cdr 工作表:
Host name Informixserver group database table 
Picc21 ld370222_tcp Grp_picc21 Picc2 * 
Ibm500 ld370220_tcp Grp_ibm500 Picc2 * 
省公司dbserver
地市1 dbserver 地市2 dbserver 地市3 dbserver 
4.2.2. 确定复制环境 
1. 复制模式:单向数据复制
2. 复制时间间隔:立即更新 
4.2.3. 建立picc21 和ibm500 的数据库之间的互访
1) 分别在picc21 和scosysv 上编辑$INformIXDIR/etc/sqlhosts 文件如下: 
grp_picc21 group - - i=1
ld370222_shm onipcshm picc21 ls370222_shm g=grp_picc21 
ld370222_tcp ontlitcp picc21 ls370222_tcp g=grp_picc21 
grp_ibm500 group - - i=2 
ld370220_shm onipcshm ibm500 ls370220_shm g=grp_ibm500 
ld370220_tcp ontlitcp ibm500 ls370220_tcp g=grp_ibm500
2) 分别在picc21 和ibm500 上的/etc/hosts 文件包括如下2 项: 
176.176.21.78 picc21 picc21 
176.176.66.103 ibm500 
3) 分别在picc21 和ibm500 上的/etc/services 文件包括如下2 项: 
ls370222_tcp 5889/tcp 
ls370220_tcp 3720/tcp 
4) 在picc21 上的/etc/hosts.equiv 文件包括如下1 项: 
ibm500 
5) 在ibm500 上的/etc/hosts.equiv 文件包括如下1 项: 
picc21
以上各步完成picc21 和ibm500 的数据库互访,可以通过dbaccess-connect 验证。 
4.2.4. 定义replicate server 
执行上$INformIXDIR/cdr/crtser.sh 
脚本内容如下:
cdr define server -s sendq -r recvq -A /tmp/ats -R /tmp/ris -I grp_picc21 
注:确保picc21 上的dbspaces sendq 和recvq 已建立
确保picc21 上的/tmp/ats 和/tmp/ris 目录已建立 
4.2.5. 确定复制服务器已建立 
执行picc21 上执行cdr list server
系统显示如下说明replicate server 已建立:
SERVER ID STATE STATUS CONNECTION CHANGED 

grp_picc21 1 Active Local 
注1. replicate server 建立时会在picc21 上建立一个名为syscdr 的database 用来 
管理所有的repliate 信息,因此也可以通过用dbaccess 命令看是否建立了
syscdr 来确定replicate server 是否正确定义。
注2. replicate 必须用DBSERVER GROUP 代替DBSERVER ( DBSERVER GROUP 在 
sqlhosts 中定义)
4.2.6. 增加连接成员: 
执行picc21 上$INformIXDIR/cdr/crtmeb.sh
脚本内容如下: TuhdxFz&
cdr define server -s datadbs -r datadbs -A /tmp/ats -R /tmp/ris 
--connect=grp_ibm500 --init --sync=grp_picc21 grp_ibm500 
注:确保ibm500 上的datadbs 和datadbs 已建立 
确保ibm500 上的/tmp/ats 和/tmp/ris 目录已建立 
4.2.7. 确定成员已连接
执行picc21 上执行cdr list server 
系统显示如下说明新成员已连接:
SERVER ID STATE STATUS CONNECTION CHANGED
grp_ibm500 2 Active Connected Dec 7 14:54:17 2001 
grp_picc21 1 Active Local 
1. 在增加一个成员时也会在ibm500 上的database server 上建立一个名为
syscdr 的database,因此除了用cdr list server 外,也可以用dbaccess 命 
令看是否建立了syscdr 来确定一个成员是否正确加入。
2. 确保picc21 和ibm500 已做时间同步(参见附录) 
4.2.8. 定义replicate 
执行picc21 上$INformIXDIR/cdr/repdef.sh 
脚本内容如下: Zq/
cdr def repl picc2_a_charge_ratio -C ignore -S row -T -R "PO
picc2@grp_picc21:cbps.a_charge_ratio" "select * from a_charge_ratio" "RO
picc2@grp_ibm500:cbps.a_charge_ratio" "select * from a_charge_ratio" 
cdr def repl picc2_a_comm_ratio -C ignore -S row -T -R "PO
picc2@grp_picc21:cbps.a_comm_ratio" "select * from a_comm_ratio" "RO 
picc2@grp_ibm500:cbps.a_comm_ratio" "select * from a_comm_ratio"
4.2.9. 确定replicate 建立 
执行picc21 上执行cdr list repl 
系统显示如下说明replicate 已建立(但为激活):
REPLICATE STATE CONFLICT FREQUENCY OPTIONS 
picc2_a_charge_ratio INACTIVE ignore immediate row,ris,triggers 
picc2_a_comm_ratio INACTIVE ignore immediate row,ris,triggers 
4.2.10. 启动replicate 
执行picc21 上$INformIXDIR/cdr/repstart.sh 
脚本内容如下:
cdr start repl picc2_a_charge_ratio 
cdr start repl picc2_a_comm_ratio
4.2.11. 确定replicate 已启动 
执行picc21 上执行cdr list repl 
系统显示如下说明replicate 已激活: 
REPLICATE STATE CONFLICT FREQUENCY OPTIONS 

picc2_a_charge_ratio ACTIVE ignore immediate row,ris,triggers 
picc2_a_comm_ratio ACTIVE ignore immediate row,ris,triggers 
4.2.12. 关闭replicate 
执行picc21 上$INformIXDIR/cdr/repstop.sh 
脚本内容如下:
cdr stop repl picc2_a_charge_ratio 
cdr stop repl picc2_a_comm_ratio 
4.2.13. 维护CDR ?/@#{J
CDR 配置完成后,系统将按照配置自动完成数据复制功能。根据需要也可以停止CDR 和
重新启动CDR,或者修改CDR 的配置。下面列出几种需要对CDR 进行维护的情况:
1. 使用dbexport 卸载数据库时,需要通过如下命令停止CDR
cdr stop 
2. 可以通过如下命令重新启动CDR 
cdr start 
3. 修改复制时间间隔时,可以通过如下命令修改replicate 的配置 
cdr modify repl -a 24:00 repl_name 
注:将复制间隔修改为每天24:00 开始复制
可以使用脚本$INformIXDIR/cdr/repmdf.sh 进行成批修改
4. 需要停止某个replicate 时,可以通过如下命令完成
cdr stop repl repl_name
注:可以使用脚本$INformIXDIR/cdr/repstop.sh 停止一批replicate 
5. 需要删除某个replicate 时,可以通过如下命令完成 
cdr delete repl repl_name
注:可以使用脚本$INformIXDIR/cdr/repdel.sh 进行成批修改 
6. 需要删除replicate server 时,可以通过如下命令完成 
cdr delete server server_name 
4.2.14. 监控CDR 工作情况 
1. 可以通过2.3、2.5 、2.7 章节中的命令分别监控replicate server、
participant 和replicate 的状态是否正常。 
2. 通过查看/tmp/ats 和/tmp/ris 目录,如有文件存在说明有复制不成功的记录,
通过vi 查看复制不成功的具体原因。
3. 通过查看$INformIXDIR/online.log 文件,判断CDR 运行情况。 
4.2.15. CDR 出错处理 
一旦有某个表的数据复制不成功, 完成如下步骤恢复该表的数据一致性:
1. Suspend 该表的复制 
2. 删除该表在复制库中的数据 
3. 从生产库unload 该表数据,再在复制库load 该表数据
4. resum 该表的复制 
4.3. CDR 的时间同步 
有关ntp(Network time protocol)的配置,必须在CDR 定义之前进行。两台主机必须 
通过ntp 做时钟同步,哪台主机做ntp Server 是无所谓的。在跨平台的情况配置有所不同 
这里介绍了两种情况:2 台SCO 主机和1 台AIX、1 台SCO
² 2 台主机都是SCO 平台
ntp Server 端:
1) 编辑/etc/ntp.conf(有可能无此文件,可以新建一个文件,其owner 和group 都是bin)
内容如下:
server 127.127.1.0 
2) 修改/etc/tcp 文件 
在/etc/tcp 文件中查xntpd 行,删除tickadj 一行,下一行的xntpd 后加-g ,
ntp Client 端:
1) 编辑/etc/ntp.conf(有可能无此文件,可以新建一个文件,其owner 和group 都是bin)
内容如下:
peer (ntp Server 的IP 地址)如:peer 11.137.75.131
2) 修改/etc/tcp 文件 
在/etc/tcp 文件中查xntpd 行,保留tickadj 一行,下一行的xntpd 后加-g 
3)跟踪两台主机ntp 是否同步成功:查/usr/adm 下的syslog
# tail -f syslog 
ntp Server 端应有ntp Server 启动的信息 
ntp Client 端应每隔5-10 分钟有与ntp Server 握手的信息 
² 1 台主机是SCO 平台,1 台主机是AIX 平台 
1)server 端必须定义在AIX 平台上且/etc/ntp.conf 文件如下
server 127.127.1.0 
fudge 127.127.1.0 refid 
注:s7a 是time server 所在的主机名 
2)xntpd -g (或/etc/rc.tcpid 中加入该行,重启机) 
3)查看两台主机是否同步:运行ntpqà readlist 
1. 存储过程的使用 
公共模块,用存储过程代替函数,可使代码统一。
Client /Server 模式,用存储过程代替函数,减少client 端应用,减少传输量,提高效率。
在SQL 语句中,需要使用存储过程处理复杂的事情。这一点在描述中使用的特别普遍。
2. 存储过程的调用 
存储过程有两种调用方式 
(1). select getday( “1998/1/1”,1,”month”) from exec 
(2). Execute procedure getday(“1998/1/1”,1,”month”) 
注:exec 为一只有一条记录的表 
当存储过程以with resume 返回,返回值超过一列时,只能用第二种调用方式。 
这两种方式有一点区别,第二种方式执行的一定是存储过程,第一种方式则不一定。
如下所示:
select mod(7,3) from exec 执行的是系统过程
execute procedure mod(7,4) 执行的是自己定义的存储过程mod。
3. 存储过程的调试 
存储过程的调试通常采用两种方法。
(1) 设置debug file ,以trace 方式。
(2) 用return .. with resume 方式调试。
例:1 
create procedure getday(t_day date,t_int int ,t_flag char(10)) returning date; 
define i int; 
define tt_day date; 
DEFINE ESQL,EISAM INT; 
DEFINE ETEXT CHAR(80); 
Set debug file to “sun.tmp”; 
let tt_day="18991231"
let i=0;
if t_flag="year" then 
while 1=1
on exception in(-1267) A|)
let i=i+1;
end exception 
let tt_day=t_day-i;
let tt_day=tt_day+t_int units year; 
trace tt_day; 
exit while; 
end while; 
elif t_flag="month" then 
while 1=1  
on exception in(-1267)  
let i=i+1;  
end exception  
let tt_day=t_day-i;  
let tt_day=tt_day+t_int units month; 
trace tt_day;  
exit while;  
end while;  
elif t_flag="day" then  
let tt_day=t_day+t_int units day;  
else  
let tt_day=t_day;  
end if; 
return tt_day;  
end procedure;  
例:2  
create procedure getday(t_day date,t_int int ,t_flag char(10)) returning date; 
define i int;  
define tt_day date;  
DEFINE ESQL,EISAM INT;  
DEFINE ETEXT CHAR(80);  
let tt_day="18991231";  
let i=0;  
if t_flag="year" then 
while 1=1 
on exception in(-1267) 
let i=i+1;
end exception  
let tt_day=t_day-i; 
let tt_day=tt_day+t_int units year; 
return tt_day with resume;
exit while;
end while; 
elif t_flag="month" then 
while 1=1 
on exception in(-1267) 
let i=i+1; 
end exception  
let tt_day=t_day-i; 
let tt_day=tt_day+t_int units month; 
return tt_day with resume; 
exit while; 
end while;
elif t_flag="day" then 
let tt_day=t_day+t_int units day; 
else 
let tt_day=t_day; 
end if; 
return tt_day; 
end procedure; 
4. 存储过程中错误的捕获 
在4gl 程序中,有whenever error continue 语句,屏蔽错误,在存储过程中不能使用 
whenever error continue,但可以使用on exception 来捕获错误,使存储过程继续执行。 
例1
create procedure get_pick_list(p_order_num int) returning int; 
define x integer; b
on exception in (-206) 
call log_error(-206); 
end exception with resume; 
select 
let x=y; 
return x; 
end procedure;  
例2 : 以下存储过程用以计算时间,标准为向前靠,如“1998/1/31”  
日加一个月为“1998/2/28” 
create procedure getday(t_day date,t_int int ,t_flag char(10)) returning date;  
define i int;  
define tt_day date;  
DEFINE ESQL,EISAM INT;  
DEFINE ETEXT CHAR(80);  
let tt_day="18991231";   
let i=0;  
if t_flag="year" then  
while 1=1  
on exception in(-1267)  
let i=i+1; 
end exception  
let tt_day=t_day-i;  
let tt_day=tt_day+t_int units year;  
exit while;  
end while;  
elif t_flag="month" then 
while 1=1 No
on exception in(-1267)
let i=i+1;  
end exception   
let tt_day=t_day-i;  
let tt_day=tt_day+t_int units month;  
exit while;  
end while;  
elif t_flag="day" then 
let tt_day=t_day+t_int units day; 
else  
let tt_day=t_day; 
end if; 
return tt_day; 
end procedure; 
注:在存储过程中,on exception 的使用有作用域,若使用在循环体内,其作用域为循环体, 
退出即退出本次循环。若使用在begin work 与commit work 内,其作用域为begin work 内,退出 
即退出该事物体。以下几个实例给予说明: 
例1:
create procedure get(t_day date,t_int int )
returning date;
define i int; 
define tt_day date; 
on exception in(-1267) ----此语句的作用域为整个存储过程
let i=i+1; ----此语句必须为存储过程的第一条语句 
end exception with resume; ------注意有with resume
set debug file to "sun.tmp";
let tt_day="18991231"
let i=0;
while 1=1
trace i;
trace tt_day; 
let tt_day=t_day-i;
let tt_day=tt_day+t_int units month; ---此处出错后执行while 循
环外的第一条语句,即下面黑色字体的语句。若无with resume 则退出存储过
程。 
trace "ok"
trace tt_day;
exit while;
end while;
trace "ok"; ---出错后执行此语句
trace tt_day;
return tt_day;
end procedure; 

例2:
create procedure get(t_day date,t_int int ) 
returning date; 
define i int;
define tt_day date;
set debug file to "sun.tmp"
let tt_day="18991231";
let i=0; 
while 1=1 
on exception in(-1267) ----此语句的作用域为while 循环
let i=i+1; ----必须为while 循环内的第一条语句 
end exception; ------注意无with resume 
trace i; 
trace tt_day; 
let tt_day=t_day-i;
let tt_day=tt_day+t_int units month; ---此处出错后执行while 循
环的下一循环,相当于continue while。若有with resume 则执行下面一条语 )
句,即黑色字体的语句。
trace "ok"
trace tt_day; 
exit while; 
end while;
trace tt_day;
return tt_day;
end procedure;
5. 存储过程的效率 
系统中的存储过程尽量放在一个extents 中,最好不要超过8 个extents. ( 注:extents 连
续的存储空间),因此可定期将系统中的所有存储过程重建。
存储过程中使用set optimization low 可提高存储过程的效率,前提是该存储过程中所涉及
的表的结构,字段无任何改动。
更为重要的是存储过程的效率与存储过程中的语句的写法很有关系。有时某一语句换一种写 
法,存储过程的效率可得到极大提高。
例如:
create procedure true_rqstart( p_main_cert like rta1.bm_cert,p_kinds like
rta1.kinds ,t_rq_start like rta1.rq_start)
returning date; 
define p_rq_start date; 
define tt_rq_start date; 
define t_bm_min char(20);
define t_bm_max char(20); 
define p_bm_cert2 char (20); 
let p_rq_start = "1899/12/31"
le tt_bm_min = p_kinds[1,3] || p_main_cert[4,7] || "0000000000000"
let t_bm_max = p_kinds[1,3] || p_main_cert[4,7] || "9999999999999"
-- foreach select bm_cert2 into p_bm_cert2 from rta1f where
--bm_cert1=p_main_cert and bm_cert2>=t_bm_min and bm_cert2<= t_bm_max 
-- select rq_start into tt_rq_start from rta1 where bm_cert = p_bm_cert2; 
-- if tt_rq_start > p_rq_start then FST
-- let p_rq_start = tt_rq_start;
-- end if; 
--end foreach; 
--以上改为以下语句,效率显著提高,从30 分到不到1 秒
--该语句有多种写法,子查询,连表等,但在该存储过程中,以下写法效率最高
foreach select bm_cert2 into p_bm_cert2 from rta1f where bm_cert1=p_main_cert
if p_bm_cert2[1,3]=p_kinds then 
select rq_start into tt_rq_start from rta1 where bm_cert = p_bm_cert2; 
if tt_rq_start > p_rq_start then 
let p_rq_start = tt_rq_start;
end if; 
end if;
end foreach; 
if p_rq_start = "1899/12/31" then 
if (t_rq_start + 35 units day ) >= today then 
return null; 
else 
return today; 
end if;
else 
if p_rq_start<>(t_rq_start -1 units year) and (t_rq_start-30 units SDP day)< (p_rq_start+1 units year) then 
let p_rq_start=p_rq_start+1 units year;
return p_rq_start; 
else 
return null; 
end if 
end if }
end procedure; 
6. 存储过程内SQL 语句执行情况的判断
   在4GL 程序中对SQL 语句执行情况的判断可用status, sqlca 等来实现。但在存储过程中,不能直接使用这些全局变量。但可通过dbinfo()来实现。
create procedure num_rows() 
returning int; 
define num_rows int; 
delete from orders where customer_num=104; 
let num_rows=dbinfo(“sqlca.sqlerrd[3]”); 
return num_rows;

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多