|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
MySQL采用双重授权(DualLicensed),它们是GPL和MySQLAB制定的商业许可协议。oracle|剧本|数据|数据库
Oracle数据库复制经常使用剧本
(石骁W 2001年07月30日17:30)
Oracle的数据复制是一个Oracle数据库产物中对照成熟的一项手艺,它是全部散布式盘算办理计划的一个主要构成部分。关于具有复制情况的数据库体系,和OracleDBA一样,一样要有一团体来专门卖力保护Oracle的数据复制成绩,称之为OracleReplicationAdministrator(Oracle复制办理员)。本文就Oracle数据复制中复制办理员常常体贴的一些关于复制体系的成绩,编写了分歧的存储历程。固然,经由过程Oracle供应的复制办理器也能够到达这些目标,但在实践使用中,Oracle复制办理用具有不天真,速率慢,同时我们不克不及对其查询了局举行随便把持等等的弱点。
1、检察Oracle8x提早事件行列挪用及挪用个数
推(push)一个年夜的提早事件(DeferredTransactions)行列长短常慢的。一个罕见的成绩就是一个事件中含有十分多的挪用(calls)。假如体系检测到一个毛病,如ora-01403(数据未找到毛病),也就是我们常说的检测到抵触,并且没有抵触打消办法,写到deferror毛病表和回滚事件的工夫就会更长,事件中假如挪用calls良多,则损耗在任何一个挪用的工夫就会以指数情势增加。
关于数据复制中每一个事件的挪用数Oracel激烈倡议不凌驾50个。上面的存储历程供应了一个疾速检察提早事件行列中的事件列表和每一个事件中挪用数的剧本。输入是以传输按次分列的,这个按次就是事件将要传布到主节点的按次。这关于断定传布中的提早和挂起等长短常有匡助的。
在搭建Oracle数据复制情况中,有一个履历是值得注重的,那就是必定要设置抵触办理计划,便可利用Oracle体系供应的几种计划,也能够本人编写剧本来完成抵触处置。为何如许说,必定要设置抵触办理计划,大概我们能够说,我们的复制情况是一个单项复制,不成能呈现抵触征象。在这里我讲一个本人的亲自履历的例子来讲明这个成绩,在实践事情中,我搭建了一个具有15个节点的初级复制情况,一个主界说节点,14个主节点,个中14个主节点向主界说节点单向传送数据。一样平常来说这类情形下不会呈现抵触。可是在实践使用中,成绩就呈现了,个中几个节点在传输了一些数据后,就挂(hang)了起来。一切大概查找的缘故原由到查了,一直发明不了成绩的根结。最初发明是因为数据传布到远程节点后,呈现了毛病,而在该节点又没有设置抵触办理计划,同时呈现毛病的该事件又具有凌驾1000条的挪用。个中有一条挪用堕落了,事件必要回滚,而这个在当地和远程节点间的回滚工夫就会以多少基数增加。就呈现了后面谈到的体系挂起(hang)的体现。这也就是说便是在基本不成能呈现抵触的体系中,因为偶尔的不定的毛病历程,批量数据的处置和没有思索复制情形下的数据导进都可形成在传布过程当中严峻的功能成绩,最严峻的情形就是体系挂起,不克不及完成一般的复制事情。最复杂和无效的举措就是在多路复制情况下设置一个体系确省的抵触处置办法来制止这类情形的产生。
上面这个存储历程就是在Oracle8情况以下出提早事件行列中的事件和事件中挪用个数的剧本,该剧本对Oracle7不撑持,这是由于Oracle8和Oracle7的复制机制产生了变更。
存储历程挪用办法:
在SQL/PLUS下,起首运转上面的设置,使存储历程的输入到屏幕上,
SETSERVEROUTPUTONSIZE200000
EXECP_LIST_TRANSACTIONS(ORA_SJJK);
个中,存储历程的参数as_destination为所要检察的事件传布到目标节点的提早行列,为数据库连接(DBLINK)名。
假如我们看到一个事件具有良多的挪用(凌驾50个),这个事件极可能就是形成提早事件行列推历程提早乃至是挂起的缘故原由。
附:存储历程剧本:下载该剧本
CREATEORREPLACEPROCEDUREREPADMIN.P_LIST_TRANSACTION(as_destinationinVARCHAR2)IS
local_nodeVARCHAR2(128);
remote_nodeVARCHAR2(128);
last_scnNUMBER;
last_tidVARCHAR2(22);
last_tdbVARCHAR2(128);
cntNUMBER;
CURSORc(last_deliveredNUMBER,last_tidVARCHAR2,last_tdbVARCHAR2)IS
selectcscn,enq_tid,
dscn,DECODE(c.recipient_key,0,D,R)
fromsystem.def$_aqcallcwhere
(c.cscn>=last_delivered)
and((c.cscn>last_delivered)or(c.enq_tid>last_tid))
and(
(c.recipient_key=0
andexists(select/*+index(cddef$_calldest_primary)*/null
fromsystem.def$_calldestcd
wherecd.enq_tid=c.enq_tid
andcd.dblink=remote_node))
or(c.recipient_key>0
and((exists(
selectnullfromsystem.repcat$_reppropP
whereP.dblink=remote_node
andP.how=1
andP.recipient_key=c.recipient_key
and((P.delivery_orderisNULL)
or(P.delivery_order<c.cscn))))
or(exists
(select/*+ordereduse_nl(rp)*/null
fromsystem.def$_aqcallcc,system.repcat$_repproprp
wherecc.enq_tid=c.enq_tid
andcc.cscnisnull
andrp.recipient_key=cc.recipient_key
andrp.how=1
andrp.dblink=remote_node
and((rp.delivery_orderisNULL)
or(rp.delivery_order<c.cscn)))))))
orderbyc.cscn,c.enq_tid;
BEGIN
SELECTNLS_UPPER(global_name)INTOlocal_nodeFROMglobal_name;
SELECTdblinkINTOremote_nodefromdeftrandest
WHEREdblinkLIKEUPPER(as_destination||%)ANDROWNUM<2;
IF(remote_nodeISNULL)THEN
DBMS_OUTPUT.PUT_LINE(不克不及断定方针节点,输出参数有误!);
RETURN;
ELSE
DBMS_OUTPUT.PUT_LINE(提早事件方针节点为:||remote_node);
DBMS_OUTPUT.PUT_LINE(-------------------------------------------);
ENDIF;
SELECTlast_delivered,last_enq_tid,dblink
INTOlast_scn,last_tid,last_tdb
FROMsystem.def$_destination
WHEREdblink=remote_node;
FORRINC(last_scn,last_tid,last_tdb)LOOP
SELECTcount(*)INTOcntFROMsystem.def$_aqcallWHEREenq_tid=r.enq_tid;
DBMS_OUTPUT.PUT_LINE(提早事件ID=||r.enq_tid||挪用个数=||to_char(cnt));
ENDLOOP;
END;
/
2、Oracle8初级复制情况设置成绩诊断剧本
要包管搭建的一个初级复制情况事情,必需包管一切的复制工具处于一般形态,关于一个初级复制情况,要反省一个复制情况中是不是一切工具均处于一般事情形态,必要反省分歧的体系字典工具,包含复制组工具,复制工具,复制计划工具等等。假如搭建的这个初级复制情况包括良多节点,每一个节点又包括几个复制计划(schema)和每一个计划又包括多个复制工具,则完成一遍反省必要作良多的反复事情,这里针对这个成绩,编写了一个复制设置成绩诊断包,只要运转该包中响应的历程,便可完成对下面提到的相干工具的诊断,给出响应诊断了局。
运转办法是,在SQL/PLUS情况下,
SQL>spool<文件名>
SQL>setserveroutputon
SQL>execrep_diag.rep_diag;
这里夸大一点,运转该包的用户,必需具有对体系字典表dba_repschema、dba_diagnose、dba_repcat和dba_repcatlog的检索(select)权限,固然,复制办理员(RepAdmin)用户是均有这些权限的。
附:初级复制情况设置成绩诊断包剧本。下载该剧本
CREATEORREPLACEPACKAGEREP_DIAGIS
PROCEDUREREP_DIAG;
PROCEDUREREP_SCHEMA;
PROCEDUREREP_OBJECT;
PROCEDUREREP_ERROR;
PROCEDUREREP_STAT;
ENDREP_DIAG;
/
CREATEORREPLACEPACKAGEBODYREP_DIAGIS
PROCEDUREREP_DIAGIS
BEGIN
REP_SCHEMA;
REP_OBJECT;
REP_ERROR;
REP_STAT;
ENDREP_DIAG;
PROCEDUREREP_SCHEMAAS
CURSORC_SCHEMAISSELECTSNAME,DBLINK,MASTERDEF
FROMSYS.DBA_REPSCHEMA;
BEGIN
DBMS_OUTPUT.PUT_LINE(复制计划明细信息);
DBMS_OUTPUT.PUT_LINE(-------------------------);
FORT_SCHEMAINC_SCHEMALOOP
DBMS_OUTPUT.PUT_LINE(计划称号:||T_SCHEMA.SNAME);
DBMS_OUTPUT.PUT_LINE(是不是为主界说节点:||T_SCHEMA.MASTERDEF);
DBMS_OUTPUT.PUT_LINE(数据库连接称号:||T_SCHEMA.DBLINK);
DBMS_OUTPUT.PUT_LINE(.);
ENDLOOP;
ENDREP_SCHEMA;
PROCEDUREREP_OBJECTAS
CURSORC_REP_OBJECTISSELECTSNAME,ONAME,TYPE,STATUS
FROMSYS.DBA_REPOBJECT;
BEGIN
DBMS_OUTPUT.PUT_LINE(复制工具);
DBMS_OUTPUT.PUT_LINE(----------------------------------);
FORT_REP_OBJECTINC_REP_OBJECTLOOP
DBMS_OUTPUT.PUT_LINE(.);
DBMS_OUTPUT.PUT_LINE(属主:||T_REP_OBJECT.SNAME);
DBMS_OUTPUT.PUT_LINE(工具称号:||T_REP_OBJECT.ONAME);
DBMS_OUTPUT.PUT_LINE(工具范例:||T_REP_OBJECT.TYPE);
DBMS_OUTPUT.PUT_LINE(形态:||T_REP_OBJECT.STATUS);
DBMS_OUTPUT.PUT_LINE(.);
ENDLOOP;
ENDREP_OBJECT;
PROCEDUREREP_ERRORIS
CURSORC_REP_ERRORISSELECTREQUEST,STATUS,MESSAGE,ERRNUM
FROMSYS.DBA_REPCATLOG;
BEGIN
DBMS_OUTPUT.PUT_LINE(复制目次毛病信息);
DBMS_OUTPUT.PUT_LINE(---------------);
FORT_REP_ERRORINC_REP_ERRORLOOP
DBMS_OUTPUT.PUT_LINE(.);
DBMS_OUTPUT.PUT_LINE(哀求:||T_REP_ERROR.REQUEST);
DBMS_OUTPUT.PUT_LINE(形态:||T_REP_ERROR.STATUS);
DBMS_OUTPUT.PUT_LINE(信息:||T_REP_ERROR.MESSAGE);
DBMS_OUTPUT.PUT_LINE(毛病:||T_REP_ERROR.ERRNUM);
DBMS_OUTPUT.PUT_LINE(.);
ENDLOOP;
ENDREP_ERROR;
PROCEDUREREP_STATIS
CURSORC_REP_STATISSELECTSNAME,MASTER,STATUS
FROMSYS.DBA_REPCAT;
BEGIN
DBMS_OUTPUT.PUT_LINE(复制形态);
DBMS_OUTPUT.PUT_LINE(------------------);
FORT_REP_STATINC_REP_STATLOOP
DBMS_OUTPUT.PUT_LINE(.);
DBMS_OUTPUT.PUT_LINE(计划:||T_REP_STAT.SNAME);
DBMS_OUTPUT.PUT_LINE(是不是主节点?:||T_REP_STAT.MASTER);
DBMS_OUTPUT.PUT_LINE(形态:||T_REP_STAT.STATUS);
DBMS_OUTPUT.PUT_LINE(.);
ENDLOOP;
ENDREP_STAT;
ENDREP_DIAG;
/
3、列出一个提早事件的一切挪用
作为一个复制办理员,我们常常必要检察某个提早事件中究竟包括那些挪用,而这些挪用的参数又是甚么。Oracle复制包中没有供应响应的剧本来完成该功效,一般我们的做法只能是借助于Oracle的复制办理器来检察,可是假如提早事件良多,且没有提早事件的挪用个数也良多的话,Oracle复制办理器十分的慢,并且最主要的是我们基本没法间接操纵这些数据。上面这个剧本能够列出提早行列中的某个事件的一切挪用内容,假如再对这个剧本加以改革的话,乃至能够恢复出提早事件中的OracleDDL语句。这关于Oracle复制办理员长短常有效的功效。
在对复制情况的办理中,还常常作如许一个事情,假如复制产生毛病,将会将毛病信息写进毛病行列中(deferror视图),体系会显现出在一个提早事件中毛病的挪用号,也能够将上面的程序加以改革,让其间接输入某个事件的某个挪用。因为在良多情形下,一个事件一般含有良多的挪用,将一切的都显现出来没有需要,实在我们更体贴个中的某个挪用。该存储历程这里就不胪陈,实在依据上面的这个历程改革长短常简单的。有感乐趣的也能够和我接洽。
存储历程p_list_calls能够列出一个提早事件中的一切挪用的参数范例和值,撑持一切的复制范例,包含NCHAR,NVARCHAR和一切的LOB.
运转办法和后面谈到的存储历程一样,起首必要将输入定位到屏幕,
setserveroutputonsize200000
个中参数存储历程的输出参数T为提早事件的ID号,能够经由过程视图deferror大概defcall失掉,上面是一个典范的挪用历程例子:
SQL>select*fromdeftran;
DEFERRED_TRAN_IDDELIVERY_ORDERDSTART_TIME
-------------------------------------------------------
7.0.374165040962R25-7月-01
8.41.374765040963R25-7月-01
6.18.373965040974R25-7月-01
8.39.374665040843R25-7月-01
SQL>setserveroutputonsize1000000
SQL>executep_list_calls(7.0.3741);
挪用按次:0
操纵:DB_ZGXT.PA_REP_JB.P_REP_DJ_NSRXX_U
参数个数:12
参数数据范例值
--------------------------------------------------------
01N_NSRNMVARCHAR2034530001
02N_PZWHVARCHAR2(NULL)
03N_TBRQDATE(NULL)
04N_BGRQDATE2000-12-2800:00:00
05N_JBRVARCHAR2(NULL)
06N_FZRVARCHAR2(NULL)
07N_SWJGYJVARCHAR2(NULL)
08N_BZVARCHAR2(NULL)
09N_RYDMVARCHAR2030811
10N_BGLRRQDATE2000-12-2814:57:01
11N_ZHWZBMVARCHAR213302030000270999999
12N_KZBZCHAR1
PL/SQL历程已乐成完成。
附:存储历程代码。下载该剧本
CREATEORREPLACEPROCEDUREP_LIST_CALLS(TINVARCHAR2)IS
ARGNONUMBER;
ARGTYPNUMBER;
ARGFORMNUMBER;
CALLNONUMBER;
TRANIDVARCHAR2(30);
TYPDSCCHAR(15);
ROWID_VALROWID;
CHAR_VALVARCHAR2(255);
NCHAR_VALNVARCHAR2(255);
DATE_VALDATE;
NUMBER_VALNUMBER;
VARCHAR2_VALVARCHAR2(2000);
NVARCHAR2_VALNVARCHAR2(2000);
RAW_VALRAW(255);
ARG_NAMEVARCHAR2(20);
ARG_NAME_CCHAR(20);
TABLE_NAMEVARCHAR2(100);
COL_NAMEVARCHAR2(100);
PK_CHARCHAR(1);
--提早行列光标
CURSORC_DEFCALL(TVARCHAR2)IS
SELECTCALLNO,DEFERRED_TRAN_ID,SCHEMANAME,PACKAGENAME,PROCNAME,ARGCOUNT
FROMDEFCALL
WHEREDEFERRED_TRAN_ID=T;
--取得参数称号
CURSORC_ARG_NAME(P_SCHEMAVARCHAR2,P_PROCNAMEVARCHAR2,
P_PKGNAMEVARCHAR2,P_CALL_COUNTVARCHAR2)IS
SELECTARGUMENT_NAME
FROMALL_ARGUMENTS
WHEREOWNER=P_SCHEMA
ANDPACKAGE_NAME=P_PKGNAME
ANDOBJECT_NAME=P_PROCNAME
AND(OVERLOAD=(SELECTOVRLD.OVERLOADFROM
(SELECTOVERLOAD,OBJECT_NAME,PACKAGE_NAME,MAX(POSITION)POS
FROMALL_ARGUMENTS
WHEREOBJECT_NAME=P_PROCNAME
ANDPACKAGE_NAME=P_PKGNAME
GROUPBYOVERLOAD,OBJECT_NAME,PACKAGE_NAME
)OVRLD
WHEREP_CALL_COUNT=OVRLD.POS
ANDOBJECT_NAME=P_PROCNAME
ANDPACKAGE_NAME=P_PKGNAME
)
OROVERLOADISNULL
)
ORDERBYPOSITION;
--该光标用来取得某个列是不是为该表的主键
CURSORPK_CURSOR(SCHEMAVARCHAR2,T_NAMEVARCHAR2,COL_NAMEVARCHAR2)IS
SELECTDECODE(COUNT(*),1,*,)
FROMDBA_CONSTRAINTST1,DBA_CONS_COLUMNST2
WHERET1.CONSTRAINT_NAME=T2.CONSTRAINT_NAME
ANDT1.OWNER=T2.OWNER
ANDT1.OWNER=SCHEMA
ANDT1.CONSTRAINT_TYPE=P
ANDT1.TABLE_NAME=T_NAME
ANDT2.COLUMN_NAMELIKECOL_NAME;
BEGIN
FORC1RECINC_DEFCALL(T)LOOP
DBMS_OUTPUT.PUT_LINE(挪用按次:||C1REC.CALLNO);
DBMS_OUTPUT.PUT_LINE(操纵:||C1REC.SCHEMANAME||.||C1REC.PACKAGENAME||.||C1REC.PROCNAME);
DBMS_OUTPUT.PUT_LINE(参数个数:||C1REC.ARGCOUNT);
DBMS_OUTPUT.PUT_LINE(参数||数据范例||值);
DBMS_OUTPUT.PUT_LINE(----------------||----------------||----------------------);
ARGNO:=1;
CALLNO:=C1REC.CALLNO;
TRANID:=C1REC.DEFERRED_TRAN_ID;
OPENC_ARG_NAME(C1REC.SCHEMANAME,C1REC.PROCNAME,C1REC.PACKAGENAME,C1REC.ARGCOUNT);
WHILETRUELOOP
IF(ARGNO>C1REC.ARGCOUNT)THEN
CLOSEC_ARG_NAME;
EXIT;
ENDIF;
ARGTYP:=DBMS_DEFER_QUERY.GET_ARG_TYPE(CALLNO,ARGNO,TRANID);
ARGFORM:=DBMS_DEFER_QUERY.GET_ARG_FORM(CALLNO,ARGNO,TRANID);
FETCHC_ARG_NAMEINTOARG_NAME;
ARG_NAME_C:=ARG_NAME;
TABLE_NAME:=SUBSTR(C1REC.PACKAGENAME,1,INSTR(C1REC.PACKAGENAME,$)-1);
COL_NAME:=SUBSTR(ARG_NAME,1,LENGTH(ARG_NAME)-5)||%;
OPENPK_CURSOR(C1REC.SCHEMANAME,TABLE_NAME,COL_NAME);
FETCHPK_CURSORINTOPK_CHAR;
CLOSEPK_CURSOR;
IF(ARGTYP=1ANDARGFORM=1)THEN
TYPDSC:=VARCHAR2;
VARCHAR2_VAL:=DBMS_DEFER_QUERY.GET_VARCHAR2_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(VARCHAR2_VAL,(NULL)));
ELSIFARGTYP=1ANDARGFORM=2THEN
TYPDSC:=NVARCHAR2;
NVARCHAR2_VAL:=DBMS_DEFER_QUERY.GET_NVARCHAR2_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(TRANSLATE(NVARCHAR2_VALUSINGCHAR_CS),(NULL)));
ELSIFARGTYP=2THEN
TYPDSC:=NUMBER;
NUMBER_VAL:=DBMS_DEFER_QUERY.GET_NUMBER_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(TO_CHAR(NUMBER_VAL),(NULL)));
ELSIFARGTYP=11THEN
TYPDSC:=ROWID;
ROWID_VAL:=DBMS_DEFER_QUERY.GET_ROWID_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(ROWID_VAL,(NULL)));
ELSIFARGTYP=12THEN
TYPDSC:=DATE;
DATE_VAL:=DBMS_DEFER_QUERY.GET_DATE_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(TO_CHAR(DATE_VAL,YYYY-MM-DDHH24:MI:SS),(NULL)));
ELSIFARGTYP=23THEN
TYPDSC:=RAW;
RAW_VAL:=DBMS_DEFER_QUERY.GET_RAW_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(RAW_VAL,(NULL)));
ELSIFARGTYP=96ANDARGFORM=1THEN
TYPDSC:=CHAR;
CHAR_VAL:=DBMS_DEFER_QUERY.GET_CHAR_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(CHAR_VAL,(NULL))|||);
ELSIFARGTYP=96ANDARGFORM=2THEN
TYPDSC:=NCHAR;
NCHAR_VAL:=DBMS_DEFER_QUERY.GET_NCHAR_ARG(CALLNO,ARGNO,TRANID);
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(TRANSLATE(NCHAR_VALUSINGCHAR_CS),(NULL))|||);
ELSIFARGTYP=113THEN
TYPDSC:=BLOB;
VARCHAR2_VAL:=DBMS_LOB.SUBSTR(DBMS_DEFER_QUERY.GET_BLOB_ARG(CALLNO,ARGNO,TRANID));
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(VARCHAR2_VAL,(NULL)));
ELSIFARGTYP=112ANDARGFORM=1THEN
TYPDSC:=CLOB;
VARCHAR2_VAL:=DBMS_LOB.SUBSTR(DBMS_DEFER_QUERY.GET_CLOB_ARG(CALLNO,ARGNO,TRANID));
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(VARCHAR2_VAL,(NULL)));
ELSIFARGTYP=112ANDARGFORM=2THEN
TYPDSC:=NCLOB;
NVARCHAR2_VAL:=DBMS_LOB.SUBSTR(DBMS_DEFER_QUERY.GET_NCLOB_ARG(CALLNO,ARGNO,TRANID));
DBMS_OUTPUT.PUT_LINE(TO_CHAR(ARGNO,09)||PK_CHAR||ARG_NAME_C||TYPDSC||||NVL(TRANSLATE(NVARCHAR2_VALUSINGCHAR_CS),(NULL)));
ENDIF;
ARGNO:=ARGNO+1;
ENDLOOP;
ENDLOOP;
END;
/
MySQL的双许可模式意味着,那些希望对数据库具有额外控制的人可以直接从数据库厂商那儿得到帮助。MySQLAB公司提供了支持和维护服务,诸如代码更新和补丁修补服务等,每年订阅费为大约3000美元。 |
|