演示基于单表的流复制案例--可以同步DDL操作
2013-09-06 15:19
441 查看
环境如下:基于表及基于用户的实验都在此环境下操作。
主库上也要做修改,像db_unique_name,global_name可以不修改。
SYS@bys2>alter system set db_unique_name=bys2 scope=spfile;
SYS@bys2>alter database rename global_name to bys2;
SYS@bys2>select * from global_name;
GLOBAL_NAME
-------------
BYS2
alter system set "_job_queue_interval"=1 scope=spfile;
alter system set aq_tm_processes=1;
alter system set streams_pool_size=100m scope=both;
alter database force logging;
BYS@bys2>select SUPPLEMENTAL_LOG_DATA_MIN,force_logging from v$database;
SUPPLEMENTAL_LOG FORCE_
---------------- ------
YES YES
SYS@bys2>col db_unique_name for a20
SYS@bys2>select name,db_unique_name from v$database;
NAME DB_UNIQUE_NAME
------------------ --------------------
BYS1 BYS2
##############################################################
sqlplus bys/bys@bys2
#############################################
CREATE USER strmadmin IDENTIFIED BY strmadmin DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT DBA to strmadmin;
exec DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('strmadmin'); -- 这一步需要SYSDBA授予
源库:
注意:如果db_domain值为空,并且global names设置为true的情况下,那么这里link关键词后面的这个“bys2”必须写目标端global_name的值,而using关键词后面的“bys2”表示的是连接目标端的SERVICE
NET NAME
BYS@bys2>select * from global_name;
GLOBAL_NAME
----------------------------------------------------------------------------------------------------
BYS2
BYS@bys2>show parameter db_domain
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_domain string
conn strmadmin/strmadmin
create database link bys2 connect to strmadmin identified by strmadmin using 'bys2';
STRMADMIN@bys1>select * from global_name@bys2;
GLOBAL_NAME
-----------------
BYS2
目标库:
conn strmadmin/strmadmin
create database link bys1 connect to strmadmin identified by strmadmin using 'bys1';
STRMADMIN@bys2>select * from global_name@bys1;
GLOBAL_NAME
---------------------
BYS1
到这一步可以关了虚拟机做个备份。
create user test8 identified by test8;
grant connect,resource to test8;
conn test8/test8
create table test1(aa number primary key);
################################################################
1.在源数据库bys1上创建Source 队列
connect strmadmin/strmadmin@bys1;
BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'SOURCE_QUEUE_TABLE',
queue_name => 'SOURCE_QUEUE',
queue_user => 'strmadmin');
END;
/
移除:
begin
dbms_streams_adm.remove_queue(
queue_name => 'SOURCE_QUEUE',
cascade => true,
drop_unused_queue_table => true);
end;
/
查看状态:
select owner,queue_table,name from dba_queues where owner='STRMADMIN';
select owner,queue_table,object_type from dba_queue_tables where owner='STRMADMIN';
########################################################
2.目标库BYS2上创建接收队列
BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'TARGET_QUEUE_TABLE',
queue_name => 'TARGET_QUEUE',
queue_user => 'strmadmin');
END;
/
查看状态:
select owner,queue_table,name from dba_queues where owner='STRMADMIN';
select owner,queue_table,object_type from dba_queue_tables where owner='STRMADMIN';
##########################################
3.源库BYS1上创建capture进程
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'test8.test1',
streams_type => 'capture',
streams_name => 'capture_stream',
queue_name => 'strmadmin.SOURCE_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'bys1',
include_tagged_lcr => false,
inclusion_rule => true);
END;
/
查看状态:
select CAPTURE_NAME,QUEUE_NAME,START_SCN,STATUS,CAPTURE_TYPE from dba_capture;
select * from ALL_CAPTURE_PREPARED_SCHEMAS;
########################################################
4.源库BYS1上创建传播进程
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name => 'test8.test1',
streams_name => 'source_to_target',
source_queue_name => 'strmadmin.SOURCE_QUEUE',
destination_queue_name => 'strmadmin.TARGET_QUEUE@bys2',
include_dml => true,
include_ddl => true,
source_database => 'bys1',
inclusion_rule => true,
queue_to_queue => true);
END;
/
查看状态:
select PROPAGATION_NAME,SOURCE_QUEUE_NAME,DESTINATION_QUEUE_NAME,DESTINATION_DBLINK,STATUS from dba_propagation;
#################################################################
5.目标库上创建APPLY进程
BEGIN
DBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'test8.test1',
streams_type => 'apply',
streams_name => 'target_apply_stream',
queue_name => 'strmadmin.TARGET_QUEUE',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'bys1',
inclusion_rule => true);
END;
/
查看状态:
select apply_name,queue_name,status from dba_apply;
########################################################
6.通过设置SCN进行实例化
查询源库的SCN
select DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER() from dual;
设置为目标库互置用户的SCN:在instantiation_scn =>处指定源库查询出来的SCN
同时要注意指定SOURCE_OBJECT_NAME =>中的用户名和source_database_name =>表名以及数据库名。
BEGIN
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
SOURCE_OBJECT_NAME => 'test8.test1',
source_database_name => 'bys1',
instantiation_scn => 1684128);
END;
如果同步需要同步两个表,实例化的写法如下:
注意SOURCE_OBJECT_NAME => 'test9.test1,test9.test2',实验中每次写一个表执行两次是不行的,需要同时写进去。
同步两个表写法:
BEGIN
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
SOURCE_OBJECT_NAME => 'test9.test1,test9.test2',
source_database_name => 'bys1',
instantiation_scn => 1673182);
END;
/
#####################################
7.在目标数据库上启动APPLY进程
BEGIN
DBMS_APPLY_ADM.START_APPLY(
apply_name => 'target_apply_stream');
END;
/
##停止APPLY进程:
begin
dbms_apply_adm.stop_apply(
apply_name => 'target_apply_stream');
end;
/
查看状态:
select apply_name,queue_name,status from dba_apply;
##################################################################
8.在源库上启动capture
BEGIN
DBMS_CAPTURE_ADM.START_CAPTURE(
capture_name => 'capture_stream');
END;
/
#停止Capture进程
begin
dbms_capture_adm.stop_capture(
capture_name => 'capture_stream');
end;
/
查看状态:
STRMADMIN@bys1>select capture_name,status,CAPTURED_SCN,APPLIED_SCN from dba_capture;
#########################
9.数据同步测试:
情景一:关闭源库Capture进程及目标库停止APPLY进程。
在源库的test8用户的test1表中插入一条数据111.目标库不插入。然后查询SCN。设置目标库SCN来进行实例化,然后启动
此时源和目标的test8用户的test1表中数据存在差异。
在源库的test8用户的test1表中插入数据,同步情况是已经存在的111条目不会传送到目标,新进行的插入操作可以传送。
源库操作:
TEST8@bys1>select * from test1;
AA
----------
111
TEST8@bys1>insert into test1 values(222);
1 row created.
TEST8@bys1>commit;
Commit complete.
TEST8@bys1>set time on
21:15:34 TEST8@bys1>insert into test1 values(333);
1 row created.
21:15:45 TEST8@bys1>commit;
Commit complete.
目标库查询操作:
TEST8@bys2>select * from test1;
no rows selected
TEST8@bys2>select * from test1;
AA
----------
222
TEST8@bys2>set time on
21:15:34 TEST8@bys2>select * from test1;
AA
----------
222
21:15:50 TEST8@bys2>select * from test1;
AA
----------
222
21:15:52 TEST8@bys2>select * from test1;---可以观察到源库的DML操作后有一定的延迟才能传送到备库。
AA
----------
222
333
Tue Sep 03 21:17:01 2013
knlbmEnq: all subscribers are inactive - stop enqueuing
解决方法是:停止源和目标库的传播和接收进程,重新实例化两个库,再重新打开源和目标库的传播和接收进程。
实验如下:
源库操作:
21:15:58 TEST8@bys1>delete test1;
3 rows deleted.
21:16:24 TEST8@bys1>commit;
Commit complete.
21:16:28 TEST8@bys1>select * from test1;
no rows selected
目标库:日志无报错,但是进程ABORTED
21:16:41 TEST8@bys2>select * from test1;
AA
----------
222
333
STRMADMIN@bys2>select apply_name,queue_name,status from dba_apply;
APPLY_NAME QUEUE_NAME STATUS
-------------------- -------------------- ----------------
TARGET_APPLY_STREAM TARGET_QUEUE ABORTED
TEST8@bys1>set time on
18:56:34 TEST8@bys1>select * from test1;
no rows selected
18:56:48 TEST8@bys1>insert into test1 values(1);
1 row created.
18:56:52 TEST8@bys1>commit;
Commit complete.
18:56:54 TEST8@bys1>select * from test1;
AA
----------
1
18:56:56 TEST8@bys1>truncate table test1;
Table truncated.
18:57:09 TEST8@bys1>select * from test1;
no rows selected
18:57:11 TEST8@bys1>
目标库查询
工TEST8@bys2>set time on
18:56:38 TEST8@bys2>select * from test1;
no rows selected
18:56:41 TEST8@bys2>
18:56:59 TEST8@bys2>select * from test1;
AA
----------
1
18:57:00 TEST8@bys2>select * from test1;
no rows selected
18:57:14 TEST8@bys2>
10:29:26 TEST8@bys1>select * from test1;
no rows selected
10:30:06 TEST8@bys1>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
TEST1 TABLE
10:30:09 TEST8@bys1>select * from test1;
no rows selected
10:30:14 TEST8@bys1>drop table test1 purge;
Table dropped.
10:30:28 TEST8@bys1>select * from tab;
no rows selected
目标库查询:
TEST8@bys2>set time on
10:29:49 TEST8@bys2>select * from test1;
no rows selected
10:29:53 TEST8@bys2>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------------------------------------ -------------- ----------
TEST1 TABLE
10:29:57 TEST8@bys2>select * from test1;
no rows selected
10:30:19 TEST8@bys2>select * from tab;
no rows selected
10:30:38 TEST8@bys2>select * from test1;
select * from test1
*
ERROR at line 1:
ORA-00942: 表或视图不存在
一、配置初始化环境
1.修改初始化参数:
目标库上:--因是使用虚拟机克隆的,所以两个库数据名和实例名一样,此时要修改目标库的db_unique_name和global_name主库上也要做修改,像db_unique_name,global_name可以不修改。
SYS@bys2>alter system set db_unique_name=bys2 scope=spfile;
SYS@bys2>alter database rename global_name to bys2;
SYS@bys2>select * from global_name;
GLOBAL_NAME
-------------
BYS2
alter system set "_job_queue_interval"=1 scope=spfile;
alter system set aq_tm_processes=1;
alter system set streams_pool_size=100m scope=both;
alter database force logging;
BYS@bys2>select SUPPLEMENTAL_LOG_DATA_MIN,force_logging from v$database;
SUPPLEMENTAL_LOG FORCE_
---------------- ------
YES YES
SYS@bys2>col db_unique_name for a20
SYS@bys2>select name,db_unique_name from v$database;
NAME DB_UNIQUE_NAME
------------------ --------------------
BYS1 BYS2
##############################################################
2.配置双方监听,在两台主机上能够通过服务名互相访问
sqlplus bys/bys@bys1sqlplus bys/bys@bys2
#############################################
3.创建用户和DBLINK---源和目标库都需要做
创建stream管理账户并赋予权限----这个操作需要SYSDBA用户创建数据链--要确认数据链可用才能做下一步CREATE USER strmadmin IDENTIFIED BY strmadmin DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;
GRANT DBA to strmadmin;
exec DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE('strmadmin'); -- 这一步需要SYSDBA授予
源库:
注意:如果db_domain值为空,并且global names设置为true的情况下,那么这里link关键词后面的这个“bys2”必须写目标端global_name的值,而using关键词后面的“bys2”表示的是连接目标端的SERVICE
NET NAME
BYS@bys2>select * from global_name;
GLOBAL_NAME
----------------------------------------------------------------------------------------------------
BYS2
BYS@bys2>show parameter db_domain
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_domain string
conn strmadmin/strmadmin
create database link bys2 connect to strmadmin identified by strmadmin using 'bys2';
STRMADMIN@bys1>select * from global_name@bys2;
GLOBAL_NAME
-----------------
BYS2
目标库:
conn strmadmin/strmadmin
create database link bys1 connect to strmadmin identified by strmadmin using 'bys1';
STRMADMIN@bys2>select * from global_name@bys1;
GLOBAL_NAME
---------------------
BYS1
到这一步可以关了虚拟机做个备份。
二、基于表的复制案例
源库名bys1,目标库名bys2,数据同步基于的表是test8用户的test1表。 提示:在涉及table_name及source_database等参数时要注意根据自己实际测试环境修改。 需要双方首先都创建test8用户并创建test1表。并且注意配置时要使用strmadmin用户。create user test8 identified by test8;
grant connect,resource to test8;
conn test8/test8
create table test1(aa number primary key);
################################################################
1.在源数据库bys1上创建Source 队列
connect strmadmin/strmadmin@bys1;BEGIN
DBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'SOURCE_QUEUE_TABLE',
queue_name => 'SOURCE_QUEUE',
queue_user => 'strmadmin');
END;
/
移除:
begin
dbms_streams_adm.remove_queue(
queue_name => 'SOURCE_QUEUE',
cascade => true,
drop_unused_queue_table => true);
end;
/
查看状态:
select owner,queue_table,name from dba_queues where owner='STRMADMIN';
select owner,queue_table,object_type from dba_queue_tables where owner='STRMADMIN';
########################################################
2.目标库BYS2上创建接收队列
BEGINDBMS_STREAMS_ADM.SET_UP_QUEUE(
queue_table => 'TARGET_QUEUE_TABLE',
queue_name => 'TARGET_QUEUE',
queue_user => 'strmadmin');
END;
/
查看状态:
select owner,queue_table,name from dba_queues where owner='STRMADMIN';
select owner,queue_table,object_type from dba_queue_tables where owner='STRMADMIN';
##########################################
3.源库BYS1上创建capture进程
BEGINDBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'test8.test1',
streams_type => 'capture',
streams_name => 'capture_stream',
queue_name => 'strmadmin.SOURCE_QUEUE',
include_dml => true,
include_ddl => true,
source_database => 'bys1',
include_tagged_lcr => false,
inclusion_rule => true);
END;
/
查看状态:
select CAPTURE_NAME,QUEUE_NAME,START_SCN,STATUS,CAPTURE_TYPE from dba_capture;
select * from ALL_CAPTURE_PREPARED_SCHEMAS;
########################################################
4.源库BYS1上创建传播进程
BEGINDBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
table_name => 'test8.test1',
streams_name => 'source_to_target',
source_queue_name => 'strmadmin.SOURCE_QUEUE',
destination_queue_name => 'strmadmin.TARGET_QUEUE@bys2',
include_dml => true,
include_ddl => true,
source_database => 'bys1',
inclusion_rule => true,
queue_to_queue => true);
END;
/
查看状态:
select PROPAGATION_NAME,SOURCE_QUEUE_NAME,DESTINATION_QUEUE_NAME,DESTINATION_DBLINK,STATUS from dba_propagation;
#################################################################
5.目标库上创建APPLY进程
BEGINDBMS_STREAMS_ADM.ADD_TABLE_RULES(
table_name => 'test8.test1',
streams_type => 'apply',
streams_name => 'target_apply_stream',
queue_name => 'strmadmin.TARGET_QUEUE',
include_dml => true,
include_ddl => true,
include_tagged_lcr => false,
source_database => 'bys1',
inclusion_rule => true);
END;
/
查看状态:
select apply_name,queue_name,status from dba_apply;
########################################################
6.通过设置SCN进行实例化
查询源库的SCNselect DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER() from dual;
设置为目标库互置用户的SCN:在instantiation_scn =>处指定源库查询出来的SCN
同时要注意指定SOURCE_OBJECT_NAME =>中的用户名和source_database_name =>表名以及数据库名。
BEGIN
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
SOURCE_OBJECT_NAME => 'test8.test1',
source_database_name => 'bys1',
instantiation_scn => 1684128);
END;
如果同步需要同步两个表,实例化的写法如下:
注意SOURCE_OBJECT_NAME => 'test9.test1,test9.test2',实验中每次写一个表执行两次是不行的,需要同时写进去。
同步两个表写法:
BEGIN
DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN(
SOURCE_OBJECT_NAME => 'test9.test1,test9.test2',
source_database_name => 'bys1',
instantiation_scn => 1673182);
END;
/
#####################################
7.在目标数据库上启动APPLY进程
BEGINDBMS_APPLY_ADM.START_APPLY(
apply_name => 'target_apply_stream');
END;
/
##停止APPLY进程:
begin
dbms_apply_adm.stop_apply(
apply_name => 'target_apply_stream');
end;
/
查看状态:
select apply_name,queue_name,status from dba_apply;
##################################################################
8.在源库上启动capture
BEGINDBMS_CAPTURE_ADM.START_CAPTURE(
capture_name => 'capture_stream');
END;
/
#停止Capture进程
begin
dbms_capture_adm.stop_capture(
capture_name => 'capture_stream');
end;
/
查看状态:
STRMADMIN@bys1>select capture_name,status,CAPTURED_SCN,APPLIED_SCN from dba_capture;
#########################
9.数据同步测试:
情景一:关闭源库Capture进程及目标库停止APPLY进程。在源库的test8用户的test1表中插入一条数据111.目标库不插入。然后查询SCN。设置目标库SCN来进行实例化,然后启动
此时源和目标的test8用户的test1表中数据存在差异。
在源库的test8用户的test1表中插入数据,同步情况是已经存在的111条目不会传送到目标,新进行的插入操作可以传送。
源库操作:
TEST8@bys1>select * from test1;
AA
----------
111
TEST8@bys1>insert into test1 values(222);
1 row created.
TEST8@bys1>commit;
Commit complete.
TEST8@bys1>set time on
21:15:34 TEST8@bys1>insert into test1 values(333);
1 row created.
21:15:45 TEST8@bys1>commit;
Commit complete.
目标库查询操作:
TEST8@bys2>select * from test1;
no rows selected
TEST8@bys2>select * from test1;
AA
----------
222
TEST8@bys2>set time on
21:15:34 TEST8@bys2>select * from test1;
AA
----------
222
21:15:50 TEST8@bys2>select * from test1;
AA
----------
222
21:15:52 TEST8@bys2>select * from test1;---可以观察到源库的DML操作后有一定的延迟才能传送到备库。
AA
----------
222
333
情景二;源库删除表中所有数据,因目标库表中不存在111,此时目标库中的接收进程ABORT,并且此删除操作不对目标库起作用。
主库日志报错如下:Tue Sep 03 21:17:01 2013
knlbmEnq: all subscribers are inactive - stop enqueuing
解决方法是:停止源和目标库的传播和接收进程,重新实例化两个库,再重新打开源和目标库的传播和接收进程。
实验如下:
源库操作:
21:15:58 TEST8@bys1>delete test1;
3 rows deleted.
21:16:24 TEST8@bys1>commit;
Commit complete.
21:16:28 TEST8@bys1>select * from test1;
no rows selected
目标库:日志无报错,但是进程ABORTED
21:16:41 TEST8@bys2>select * from test1;
AA
----------
222
333
STRMADMIN@bys2>select apply_name,queue_name,status from dba_apply;
APPLY_NAME QUEUE_NAME STATUS
-------------------- -------------------- ----------------
TARGET_APPLY_STREAM TARGET_QUEUE ABORTED
情景三:对TEST1表进行TRUNCATE--DDL操作,可以同步。
源库操作:TEST8@bys1>set time on
18:56:34 TEST8@bys1>select * from test1;
no rows selected
18:56:48 TEST8@bys1>insert into test1 values(1);
1 row created.
18:56:52 TEST8@bys1>commit;
Commit complete.
18:56:54 TEST8@bys1>select * from test1;
AA
----------
1
18:56:56 TEST8@bys1>truncate table test1;
Table truncated.
18:57:09 TEST8@bys1>select * from test1;
no rows selected
18:57:11 TEST8@bys1>
目标库查询
工TEST8@bys2>set time on
18:56:38 TEST8@bys2>select * from test1;
no rows selected
18:56:41 TEST8@bys2>
18:56:59 TEST8@bys2>select * from test1;
AA
----------
1
18:57:00 TEST8@bys2>select * from test1;
no rows selected
18:57:14 TEST8@bys2>
情景四:对TEST1表进行DROP--DDL操作,可以同步。
TEST8@bys1>set time on10:29:26 TEST8@bys1>select * from test1;
no rows selected
10:30:06 TEST8@bys1>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
TEST1 TABLE
10:30:09 TEST8@bys1>select * from test1;
no rows selected
10:30:14 TEST8@bys1>drop table test1 purge;
Table dropped.
10:30:28 TEST8@bys1>select * from tab;
no rows selected
目标库查询:
TEST8@bys2>set time on
10:29:49 TEST8@bys2>select * from test1;
no rows selected
10:29:53 TEST8@bys2>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------------------------------------ -------------- ----------
TEST1 TABLE
10:29:57 TEST8@bys2>select * from test1;
no rows selected
10:30:19 TEST8@bys2>select * from tab;
no rows selected
10:30:38 TEST8@bys2>select * from test1;
select * from test1
*
ERROR at line 1:
ORA-00942: 表或视图不存在
相关文章推荐
- 演示基于用户进行流复制案例-可以同步用户的DDL操作
- 基于信号量与P/V操作同步机制的读者/写者问题的设计与实现 (写者优先)
- Vmware vSphere让本地和虚拟机可以通过复制和粘贴操作
- 快速笔记02-MySQL主从复制原理半同步操作步骤及原理
- 基于吉日嘎底层架构的Web端权限管理操作演示-组织机构管理
- 这2天参加WinHEC大会,园子里以有很多介绍,就不多说了,会上用手机录了一段windows 最新触摸屏操作技术演示,可以看看
- 基于指纹考勤机的真实的PHP操作Access数据库成功案例(最终实现) 2011-11-2v
- Mariadb 主从复制、双主复制、半同步复制、基于SSL复制
- Visual Basic Winsock API操作模块(基于API方式的socket同步阻塞通讯类)
- MySQL 5.7 基于GTID的半同步复制
- MySQL主从复制原理、半同步操作步骤及原理
- learning jQuery 学习笔记十三(+jQuery 1.4.1 API)-- DOM操作-基于命令改变页面 ----复制元素及其它
- MySQL主从复制、基于SSL的主从复制、主主复制、半同步复制
- MariaDB数据库主从复制、双主复制、半同步复制、基于SSL的安全复制实现及其功能特性介绍(一)
- 第76课:Spark SQL基于网站Log的综合案例实战之Hive数据导入、Spark SQL对数据操作每天晚上20:00YY频道现场授课频道68917580
- 一个演示多线程操作及同步的C#程序
- jQuery移动和复制dom节点实用DOM操作案例
- 数据同步复制技术(一)---实践操作全过程图文并貌 推荐
- 【ORACLE 高可用】 ORACLE STREAM 基于单表的流复制 配置 案例
- 基于自己封装的微信api操作案例