通常我们知道,DB2的package在统计信息或依赖对象发生变化后需要做下重新绑定,否则DB2优化器会采用效率较差或者错误的执行计划运行该package,造成执行性能严重下降或者SP一直会处于卡死状态。所以定期对SP进行重新绑定操作,对数据库整体性能和效率都有较大的提升,但是查一查,关于DB2的SP重新绑定,提供了三个命令:db2rbind、rebind和bind,很多人都分不清这三者区别,如何使用的问题,所以本文就重点对着三个命令用法进行分析。

其实三者都是提供SP重新绑定,不过传入参数不一样,bind需要带入.bnd的文件,缺陷情况下,C或嵌入式SQL编写的SP在precompile时,都会创建一个以.bnd的结尾的文件,数据库中使用程序包和应用程序编译的原因相同,即就是提高性能和压缩,在程序包构建过程而不是执行过程中,SP中的相关语法语义都得到分析,并且程序包中存储的是被解释效率更高的操作字符组,在服务器管理器调用预编译生生成的代码,只需要提供相应的输入变量就可以执行执行,提高了效率。并且预编译仅仅适用静态SQL,而不适合如prepare execute和execute immediate 动态SQL。这些动态SQL还是需要重新进行编译解释。db2提供绑定文件描述工具db2bfd工具可以查看bnd文件。其用法如下:

C:\Program Files (x86)\IBM\SQLLIB\bnd>db2bfd

Usage:   db2bfd [ [-b] [-h] [-s] [-v] ] <filespec>

       Where:   <filespec> is at least a V7 bind file

       Options: -b = display bind file header
                -h = display this information
                -s = display SQL statements
                -v = display host variable declarations

C:\Program Files (x86)\IBM\SQLLIB\bnd>db2bfd -b db2sampl_SQL.bnd

db2sampl_SQL.bnd:  Header Contents

Header Fields:

Field   Value
-----   -----
releaseNum      0x800
Endian  0x4c
numHvars        16
maxSect         14
numStmt         26
optInternalCnt  4
optCount        10


Name                Value
------------------  -----
Isolation Level     Cursor Stability
Creator             "NULLID  "
App Name            "SQLE6H02"
Timestamp           "AAAAABIU:2004/08/01 00:00:00:00"
Cnulreqd            Yes
Sql Error           No package
Block               Block All
Validate            Bind
Date                Default/local
Time                Default/local


*** All other options are using default settings as specified by the server ***



C:\Program Files (x86)\IBM\SQLLIB\bnd>db2bfd -s db2sampl_SQL.bnd

db2sampl_SQL.bnd:  SQL Statements = 26

Line Sec Typ Var Len SQL statement text
---- --- --- --- --- ---------------------------------------------------------
 55   0   5   0  21 BEGIN DECLARE SECTION
 76   0   2   0  19 END DECLARE SECTION
275   0  14   0  32 WHENEVER SQLERROR GOTO ENDOFPROC
3366   1   9   1  26 EXECUTE IMMEDIATE :H00001
3416   2   0   1  40 VALUES CURRENT SQLID INTO :H00008
3418   3   0   1  32 SET CURRENT SQLID = :H00009
3437   4   0   1  34 SET CURRENT SQLID = :H00008
3459   5   0   1  40 VALUES CURRENT SQLID INTO :H00008
3461   6   0   1  32 SET CURRENT SQLID = :H00009
3547   7  11   1  24 PREPARE S1 FROM :H00001
3582   7  11   1  24 PREPARE S1 FROM :H00001
3598   8   0   1  34 SET CURRENT SQLID = :H00008
3616   0   5   0  21 BEGIN DECLARE SECTION
3619   0   2   0  19 END DECLARE SECTION
3652   7   9   4  56 EXECUTE S1 USING :H00004     , :H00015, :H00005, :H00006
3674   7   9   4  56 EXECUTE S1 USING :H00004     , :H00016, :H00005, :H00006
3720   9   0   1  41 VALUES CURRENT SCHEMA INTO :H00008
3774  10   0   1  33 SET CURRENT SCHEMA = :H00009
3977  11  11   1  32 PREPARE BLOBUPDATE FROM :H00001
4005  12  11   1  32 PREPARE CLOBUPDATE FROM :H00001
4248  13   0   1  86 SELECT NUM_DB_STORAGE_PATHS INTO :H00014               FR
                    OM TABLE(SNAP_GET_DB('', -1))
4416  14   0   1  35 SET CURRENT SCHEMA = :H00008
4475  11   9   3  58 EXECUTE BLOBUPDATE using :H00010  , :H00005, :H00012

4492  11   9   3  58 EXECUTE BLOBUPDATE using :H00010  , :H00005, :H00012

4551  12   9   3  59 EXECUTE CLOBUPDATE using :H00011  , :H00005, :H00013

4573  12   9   3  59 EXECUTE CLOBUPDATE using :H00011  , :H00005, :H00013

确切来说package都是用如C等嵌入式语言开发编译而来,所以在执行绑定操作,我们通常需要使用bind,因为bind命令需要传入bnd参数文件名称,如:

C:\Program Files (x86)\IBM\SQLLIB\bnd>db2 bind db2sampl_SQL.bnd

LINE    MESSAGES FOR db2sampl_SQL.bnd
------  --------------------------------------------------------------------
       SQL0061W  The binder is in progress.
       SQL0091N  Binding was ended with "0" errors and "0" warnings.
就是将这个程序包和当前数据库绑定。当然还有其他参数,对于每个单独进行预编译的源代码模块,都将创建一个程序包。如果应用程序有 5 个源文件,其中 3 个需要进行预编译,那么将创建 3 个程序包或绑定文件。缺省情况下,为每个程序包指定的名称与 .bnd 文件所基于的源模块的名称相同,但此名称将被截断为 8 个字符。要以显式方式指定另一个程序包名,必须在 PREP 命令中使用 PACKAGE USING 选项。程序包的版本由 VERSION 预编译选项指定,并且缺省为空字符串。如果这个新创建的程序包的名称和模式与目标数据库中当前存在的某个程序包相同,但版本标识有所不同,那么将创建新程序包并保留先前的程序包。但是,如果存在与所绑定程序包的名称、模式和版本匹配的程序包,那么该程序包将被删除并替换为正在绑定的新程序包。如果绑定时指定了 ACTION ADD,那么将不允许发生这种情况,而是返回错误(SQL0719)。

如下都是一些系统默认的绑定文件名称,其实都是DB2提供的实用程序包的绑定文件,这些文件当然也是采用了C等嵌入式语言开发的SP。但大部分我们的程序包都是用SQL语言开发的SP,所以这个时候一般都是用rebind

C:\Program Files (x86)\IBM\SQLLIB\bnd>ls
ASNDONE.bnd            asnmdata.bnd           asntdiff.bnd           db2advmisc.bnd         db2dropv.bnd           db2stats.bnd           ddcsvm.lst
ASNLOAD.bnd            asnmig4c.bnd           asntdiff.lst           db2advmqt.bnd          db2dsproc.bnd          db2uImpInsUpdate.bnd   ddcsvse.lst
altobj_sp.bnd          asnmig8.bnd            asntdsql.bnd           db2advsimulation.bnd   db2evmon.bnd           db2ubind.lst           gseClAdv.bnd
altobj_util.bnd        asnmoncs.lst           asnuow.bnd             db2advworkload.bnd     db2exdyn.bnd           db2ucktb.bnd           gseClIdx.bnd
applycs.lst            asnmonit.bnd           bhunt.bnd              db2ajgrt.bnd           db2exfmt.bnd           db2ueiwi.bnd           gseClSQL.bnd
applyur.lst            asnmonit.lst           cAdmCancelWork.bnd     db2am.bnd              db2exmig.bnd           db2uexpm.bnd           hleoFwMine.bnd
asnaapp.bnd            asnmonur.lst           cAdmGetConfig.bnd      db2arxcs.bnd           db2expln.bnd           db2ugtpi.bnd           hleoFwPop.bnd
asnacmp.bnd            asnmproc.bnd           cAdmGetMessage.bnd     db2arxnc.bnd           db2exsrv.bnd           db2uiDescribe.bnd      mdcadvise.bnd
asnadmin.bnd           asnmupdt.bnd           cAdmGetPlanHint.bnd    db2arxrr.bnd           db2gpmap.bnd           db2uiXmlparse.bnd      mqlConfig.bnd
asnadmsp.bnd           asnprune.bnd           cAdmGetSystemInfo.bnd  db2arxrs.bnd           db2lk390.bnd           db2uigsi.bnd           mqlRun.bnd
asnafet.bnd            asnqahkt.bnd           cAdmSetConfig.bnd      db2arxur.bnd           db2lkfun.bnd           db2uiici.bnd           partadvise.bnd
asnaiso.bnd            asnqapag.bnd           cAdmSetPlanHint.bnd    db2ats_sps.bnd         db2lkmig.bnd           db2uiict.bnd           psmgtptp.bnd
asnaman.bnd            asnqapp.bnd            capture.lst            db2cat.bnd             db2lksp.bnd            db2uimpm.bnd           qapply.lst
asnanalyze.bnd         asnqarow.bnd           db2ExplainRtns.bnd     db2cli.lst             db2look.bnd            db2uimtb.bnd           qcapture.lst
asnappwk.bnd           asnqasub.bnd           db2_adminotm.bnd       db2clipk.bnd           db2move.bnd            db2uipkg.bnd           redistrb.bnd
asnaprs.bnd            asnqbrwz.bnd           db2_aram.bnd           db2clist.bnd           db2pctsp.bnd           db2ulxld.bnd           reval.bnd
asnawpn.bnd            asnqload.bnd           db2admDbUtil.bnd       db2clpcs.bnd           db2policy.bnd          db2updv97.bnd          sgSql.bnd
asnccpwk.bnd           asnqmon.bnd            db2admcs.bnd           db2clpnc.bnd           db2rbind.bnd           db2uqtnm.bnd           snaputil.bnd
asncdins.bnd           asnqp2pa.bnd           db2advcatalog.bnd      db2clprr.bnd           db2sampl_SQL.bnd       db2uqtpd.bnd           st_admin.bnd
asncmon.bnd            asnqp2pi.bnd           db2advindex.bnd        db2clprs.bnd           db2sampl_V8.bnd        db2uredp.bnd           tbscont.bnd
asndb2cn.bnd           asnqspil.bnd           db2advio.bnd           db2clpsy.bnd           db2sampl_XML.bnd       db2xdbmig.bnd          xdb.lst
asndb2sq.bnd           asnreg.bnd             db2advis.bnd           db2clpur.bnd           db2schema.bnd          db2xdbsg.bnd           xdbSPImpl.bnd
asndbcon.bnd           asnsqlcd.bnd           db2advisSP.bnd         db2common.bnd          db2spcat.bnd           ddcs400.lst            xdbSPutil.bnd
asnluwcon.bnd          asntdapi.bnd           db2advmdc.bnd          db2dclgn.bnd           db2spcdb.bnd           ddcsmvs.lst            xdbTupleWriter.bnd

其实工作中我们最常用的还是rebind命令,db2 rebind package packagename,不过该pakagename是存储在数据库中的P打头的数字名称,无法使用直接创建的名称,所以rebind前需要获取这个名称。一般可以这样获取:

db2 "select ' db2 rebind package '||rtrim(r.routineschema)||'.'||'P'||substr(char(r.lib_id+10000000),2) from syscat.routines r where r.routinetype = 'P'"

但其实不是所有的SP都有lib_id的,所以貌似这个不能绑定像上面的嵌入式程序包。

最后再说db2rbind,这个其实最简单,可以选择只绑定无效的程序包或者整库绑定,因而无法指定对个别SP进行绑定,当然在数据库刚恢复或升级了,就需要重新bind,否则无法使用新的包,并且还得使用replace参数才能完全覆盖之前的包中的信息,为了保证性能,可以这样做,后期的维护中大部分都不需要整库进行绑定,当对表的统计信息进行更新,创建索引,或者reorg操作了,就的需要对依赖的SP做一个rebind,以便于更新package中存储的解释执行信息。

默认这三个工具绑定的效果都是一样的,不同的是,各自有各自的参数,尤其是rebind和bind,绑定参数的使用有的时候直接对性能有很大的提升。

还有,现在DB2提供了一些管理例程工具就像这个专门做SP的重新绑定操作,只需要指定SP例程的类型和名称,当然也可以指定像rebind等指定的参数可选项,就可以对SP进行绑定了,如下:

CALL SYSPROC.REBIND_ROUTINE_PACKAGE ('P','SODS0.DP_INSRT_RT_VALID_SALES_ORD','')