ITPUB论坛-专业的IT技术社区

标题: 关于Oracle Stream的安装、配置和使用 [打印本页]

作者: bq_wang    时间: 2008-12-21 23:06
标题: 关于Oracle Stream的安装、配置和使用
关于OracleStream的安装、配置和使用

因项目预研需要,所以想找一个能够满足内外网数据库同步方案,前面先是测试了一下Oracle的高级复制功能,未果;才转而进行Oracle Stream的测试,大概是我水平太差了,前后测试了3.5遍总算把Oracle Stream运行正常起来了。
错误的原因其实称不上原因,无他,读文档读的不细致,手误、本身对这方面也缺乏理论认识。
关于Oracle流的原理
Oracle 流能够共享信息。Oracle流每个单元的共享信息来自于消息,我们可以在流中共享这些消息。流可以在同一个数据库或不同数据库之间传播信息。流路由指定信息到达特定的目的地。流比起传统的在不同数据库之间捕获、管理、共享消息的解决方案,有着更强大的功能和灵活性。流提供的功能可用于分布式企业程序、数据仓库和高可用性解决方案。我们可以在同一时刻使用oracle流的所有功能。我们可以使用流的新功能而不会严重影响数据库的性能。
使用Oracle流,我们可以控制流里的信息,流的流向,流进入目标数据库时,消息怎样运作,中止流。通过配置流,可以满足我们的特殊需求。基于我们的特殊情况,流可以在数据库里自动捕获、传播和管理DMLDDL消息。我们可以把用户定义的消息放入流中,流可以自动把信息传播到其它数据库或应用程序。当消息到达目的数据库时,流可以根据我们的设定应用它们。

本文主要参考文档《Step by step 配置Oracle Stream》杨宝秋(hrb_qiuyb)
stream_concepts_administration_读书笔记.doc》具体参见
http://www.itpub.net/thread-849868-1-1.html

试验环境采用虚拟机方式,操作系统Windows2003Oracle版本10.2.0
  
数据源机器配置
  
  
目标机器配置
  
  
计算机名
  
  
Source
  
  
Dest
  
  
IP地址
  
  
192.168.23.130
  
  
192.168.23.131
  
  
SID
  
  
Source
  
  
Dest
  

第一步:进行Stream前的参数配置,SourceDest机器上均运行,运行命令可完全一致
  SQL> conn  sys/inxite as sysdba;
  已连接。
  SQL> alter  system set aq_tm_processes=2 scope=both;
  系统已更改。
  SQL> alter  system set global_names=true scope=both;
  系统已更改。
  SQL> alter  system set job_queue_processes=20 scope=both;
  系统已更改。
  SQL> alter  system set parallel_max_servers=20 scope=both;
  系统已更改。
  SQL> alter  system set undo_retention=3600 scope=both;
  系统已更改。
  SQL> alter  system set nls_date_format='YYYY-MM-DD HH24:MI:SS' scope=spfile;
  系统已更改。
  SQL> alter  system set streams_pool_size=25M scope=spfile;
  系统已更改。
  SQL> alter  system set utl_file_dir='*' scope=spfile;
  系统已更改。
  SQL> alter  system set open_links=4 scope=spfile;
  系统已更改。
  SQL> alter  system set log_archive_dest='e:/OracleDB/arch' scope=spfile;
  系统已更改。
  SQL> alter  system set log_archive_start=TRUE scope=spfile;
  系统已更改。
  SQL> alter  system set log_archive_format='arch%t_%s_%r.arc' scope=spfile;
  系统已更改。
  

第二步:查看系统归档状态(双机可以同时检查,检查方式完全一致)
  SQL> shutdown  immediate
  数据库已经关闭。
  已经卸载数据库。
  ORACLE 例程已经关闭。
  SQL> startup  mount
  ORA-32004:  obsolete and/or deprecated parameter(s) specified
  ORACLE 例程已经启动。
  Total System  Global Area
167772160 bytes

  Fixed Size
1247900 bytes

  Variable  Size
92276068 bytes

  Database  Buffers
71303168 bytes

  Redo  Buffers
2945024 bytes

  数据库装载完毕。
  SQL> alter  database archivelog;
  数据库已更改。
  SQL> alter  database open;
  数据库已更改。
  SQL> archive  log list;
  数据库日志模式
存档模式
  自动存档
启用
  存档终点
USE_DB_RECOVERY_FILE_DEST

  最早的联机日志序列
1

  下一个存档日志序列
2

  当前日志序列
2

  SQL>
  

第三步:创建Stream用户和表空间(双机可以同时设置,设置方式完全一致)
  #创建主环境Stream专用表空间
  SQL> create  tablespace tbs_stream datafile 'e:/OracleDB/tbs_stream01.dbf'
  
2
size 100m autoextend on next 100m maxsize 1000m segment space  management auto;

  表空间已创建。
  #logminer 的数据字典从system表空间转移到新建的表空间,防止撑满system表空间
  SQL> execute  dbms_logmnr_d.set_tablespace('tbs_stream');
  PL/SQL 过程已成功完成。
  #创建Stream管理用户
  SQL> create  user strmadmin identified by strmadmin default tablespace tbs_stream
  
temporary tablespace temp;

  用户已创建。
  #授权Stream管理用户
  SQL> grant  connect,resource,dba,aq_administrator_role to strmadmin;
  授权成功。
  SQL> begin
  
2
dbms_streams_auth.grant_admin_privilege(

  
3
grantee => 'strmadmin',

  
4
grant_privileges => true);

  
5
end;

  
6
/

  PL/SQL 过程已成功完成。
  

第四步:配置各自双方的数据库连接
  source机器上添加dest数据源,名称为dest
  dest机器上添加source数据源,名称为source
  

第五步:启用追加日志
可以基于Database级别或Table级别,启用追加日志(Supplemental Log)。在建立根据Schema
粒度进行复制的Oracle Stream 环境中,如果确认Schema 下所有Table 都有合理的主键
(Primary Key),则不再需要启用追加日志。
  #启用Database 追加日志
  SQL> alter  database add supplemental log data;
  数据库已更改。
  #启用Table追加日志
  SQL> ALTER  DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE, FOREIGN KEY)
  
COLUMNS;

  

第六步:创建主数据库数据库链,以连接到从数据库
首先查看两台Oracle服务器的域名是否一致,如果不一致,需要alter database rename global_name to xxx
  SQL> select *  from global_name;
  GLOBAL_NAME
  --------------------------------------------------------------------------------
  SOURCE.REGRESS.RDBMS.DEV.US.ORACLE.COM
  SQL>conn  strmadmin/strmadmin;
  SQL> create  database link dest connect to strmadmin identified by strmadmin using 'dest';
  数据库链接已创建。
  SQL> select *  from tab@dest;
  未选定行
  

第七步:创建从数据库数据库链,以连接到主数据库
  SQL> select *  from global_name;
  GLOBAL_NAME
  --------------------------------------------------------------------------------
  DEST.REGRESS.RDBMS.DEV.US.ORACLE.COM
  SQL>conn  strmadmin/strmadmin
  SQL> create  database link source connect to strmadmin identified by strmadmin using  'source';
  数据库链接已创建。
  SQL> select *  from tab@source;
  未选定行
  

第八步:创建Master()流队列
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.set_up_queue(

  
3
queue_table => 'source_queue_table',

  
4
queue_name => 'source_queue');

  
5
end;

  
6
/

  PL/SQL 过程已成功完成。
  

第九步:创建Backup(目标)流队列
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.set_up_queue(

  
3
queue_table => 'dest_queue_table',

  
4
queue_name => 'dest_queue');

  
5
end;

  
6
/

  PL/SQL 过程已成功完成。
  

第十步:确保需要复制源机器上Schema对象的存在,并将Schema导出
  exp  userid=test/test@source file='e:/test.dmp' object_consistent=y rows=y
  

第十一步:将Schema对象导入到目标数据库上,如果不存在则创建相应的Schema,最好和源数据库各种属性保持一致,因为我这边莫名其妙发生了点错误。导致从数据库的流Apply进程为异常状态。
  imp  userid=test/test@dest file='e:/test.dmp' ignore=y commit=y log='e:/test.log' streams_instantiation=y  fromuser=test touser=test
  

第十二步:在master(源机器上)创建捕获进程
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.add_schema_rules(

  
3
schema_name => 'test',

  
4
streams_type => 'capture',

  
5
streams_name => 'capture_source',

  
6
queue_name => 'strmadmin.source_queue',

  
7
include_dml => true,

  
8
include_ddl => true,

  
9
include_tagged_lcr => false,

  
10
source_database => null,

  
11
inclusion_rule => true);

  
12
end;

  
13
/

  PL/SQL 过程已成功完成。
  

第十三步:在master(源机器上)创建传播进程
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.add_schema_propagation_rules(

  
3
schema_name => 'test',

  
4
streams_name => 'source_to_dest',

  
5
source_queue_name => 'strmadmin.source_queue',

  
6
destination_queue_name => 'strmadmin.dest_queue@dest',

  
7
include_dml => true,

  
8
include_ddl => true,

  
9
include_tagged_lcr => false,

  
10
source_database => 'source',

  
11
inclusion_rule => true);

  
12
end;

  
13
/

  PL/SQL 过程已成功完成。
  #修改propagation休眠时间为0,表示实时传播LCR
  SQL> begin
  
2
dbms_aqadm.alter_propagation_schedule(

  
3
queue_name => 'source_queue',

  
4
destination => 'dest',

  
5
latency => 0);

  
6
end;

  
7
/

  PL/SQL 过程已成功完成。
  

第十四步:在Backup(目标机器上)创建应用进程
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.add_schema_rules(

  
3
schema_name => 'test',

  
4
streams_type => 'apply',

  
5
streams_name => 'apply_dest',

  
6
queue_name => 'strmadmin.dest_queue',

  
7
include_dml => true,

  
8
include_ddl => true,

  
9
include_tagged_lcr => false,

  
10
source_database => 'source',

  
11
inclusion_rule => true);

  
12
end;

  
13
/

  PL/SQL 过程已成功完成。
  

第十五步:在Backup(目标机器上)启动Apply进程
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_apply_adm.start_apply(

  
3
apply_name => 'apply_dest');

  
4
end;

  
5
/

  PL/SQL 过程已成功完成。
  

第十六步:在Master(源机器上)启动Capture进程
  SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_capture_adm.start_capture(

  
3
capture_name => 'capture_source');

  
4
end;

  
5
/

  PL/SQL 过程已成功完成。
  




作者: yxyup    时间: 2008-12-21 23:23
牛,不错
作者: crane-zy8    时间: 2008-12-21 23:49
好,顶!
作者: adminsys    时间: 2008-12-22 00:11
非常不错
作者: Sea_jk    时间: 2008-12-22 08:44
顶啊,牛仁
作者: 伊斯力    时间: 2008-12-22 09:12
支持支持  学习学习
作者: xsmdel    时间: 2008-12-22 09:16
顶顶
作者: wenaini    时间: 2008-12-22 09:26
bug实在太多- -
作者: ward    时间: 2008-12-22 09:28
原帖由 wenaini 于 2008-12-22 09:26 发表
bug实在太多- -



实际中BUG很大吗?最近正准备上。
作者: wenaini    时间: 2008-12-22 09:31
原帖由 ward 于 2008-12-22 09:28 发表



实际中BUG很大吗?最近正准备上。

想要晚上被频繁电话问候可以用用,我测试到最高的版本是10204。。。。。。。。。。。。。。bug起码10+,而且oracle推荐的补丁已经全部打过鸟
作者: nmghailang    时间: 2008-12-22 09:38
不错,那天试试,谢谢啊
作者: weiranjie    时间: 2008-12-22 10:17
原帖由 bq_wang 于 2008-12-21 23:06 发表
关于OracleStream的安装、配置和使用
因项目预研需要,所以想找一个能够满足内外网数据库同步方案,前面先是测试了一下Oracle的高级复制功能,未果;才转而进行Oracle Stream的测试,大概是我水平太差了,前后测试了3.5遍总算把Oracle Stream运行正常起来了。
错误的原因其实称不上原因,无他,读文档读的不细致,手误、本身对这方面也缺乏理论认识。
关于Oracle流的原理
Oracle 流能够共享信息。Oracle流每个单元的共享信息来自于消息,我们可以在流中共享这些消息。流可以在同一个数据库或不同数据库之间传播信息。”流路由”指定信息到达特定的目的地。流比起传统的在不同数据库之间捕获、管理、共享消息的解决方案,有着更强大的功能和灵活性。流提供的功能可用于分布式企业程序、数据仓库和高可用性解决方案。我们可以在同一时刻使用oracle流的所有功能。我们可以使用流的新功能而不会严重影响数据库的性能。
使用Oracle流,我们可以控制流里的信息,流的流向,流进入目标数据库时,消息怎样运作,中止流。通过配置流,可以满足我们的特殊需求。基于我们的特殊情况,流可以在数据库里自动捕获、传播和管理DML、DDL消息。我们可以把用户定义的消息放入流中,流可以自动把信息传播到其它数据库或应用程序。当消息到达目的数据库时,流可以根据我们的设定应用它们。
574625
本文主要参考文档《Step by step 配置Oracle Stream》杨宝秋(hrb_qiuyb)
《stream_concepts_administration_读书笔记.doc》具体参见
http://www.itpub.net/thread-849868-1-1.html

试验环境采用虚拟机方式,操作系统Windows2003,Oracle版本10.2.0
       数据源机器配置      目标机器配置        计算机名      Source      Dest        IP地址      192.168.23.130      192.168.23.131        SID      Source      Dest   
第一步:进行Stream前的参数配置,Source和Dest机器上均运行,运行命令可完全一致
     SQL> conn  sys/inxite as sysdba;
  已连接。
  SQL> alter  system set aq_tm_processes=2 scope=both;
  系统已更改。
  SQL> alter  system set global_names=true scope=both;
  系统已更改。
  SQL> alter  system set job_queue_processes=20 scope=both;
  系统已更改。
  SQL> alter  system set parallel_max_servers=20 scope=both;
  系统已更改。
  SQL> alter  system set undo_retention=3600 scope=both;
  系统已更改。
  SQL> alter  system set nls_date_format='YYYY-MM-DD HH24:MI:SS' scope=spfile;
  系统已更改。
  SQL> alter  system set streams_pool_size=25M scope=spfile;
  系统已更改。
  SQL> alter  system set utl_file_dir='*' scope=spfile;
  系统已更改。
  SQL> alter  system set open_links=4 scope=spfile;
  系统已更改。
  SQL> alter  system set log_archive_dest='e:/OracleDB/arch' scope=spfile;
  系统已更改。
  SQL> alter  system set log_archive_start=TRUE scope=spfile;
  系统已更改。
  SQL> alter  system set log_archive_format='arch%t_%s_%r.arc' scope=spfile;
  系统已更改。
   
第二步:查看系统归档状态(双机可以同时检查,检查方式完全一致)
     SQL> shutdown  immediate
  数据库已经关闭。
  已经卸载数据库。
  ORACLE 例程已经关闭。
  SQL> startup  mount
  ORA-32004:  obsolete and/or deprecated parameter(s) specified
  ORACLE 例程已经启动。
  Total System  Global Area
167772160 bytes
  Fixed Size
1247900 bytes
  Variable  Size
92276068 bytes
  Database  Buffers
71303168 bytes
  Redo  Buffers
2945024 bytes
  数据库装载完毕。
  SQL> alter  database archivelog;
  数据库已更改。
  SQL> alter  database open;
  数据库已更改。
  SQL> archive  log list;
  数据库日志模式
存档模式
  自动存档
启用
  存档终点
USE_DB_RECOVERY_FILE_DEST
  最早的联机日志序列
1
  下一个存档日志序列
2
  当前日志序列
2
  SQL>
   
第三步:创建Stream用户和表空间(双机可以同时设置,设置方式完全一致)
     #创建主环境的Stream专用表空间
  SQL> create  tablespace tbs_stream datafile 'e:/OracleDB/tbs_stream01.dbf'
  
2
size 100m autoextend on next 100m maxsize 1000m segment space  management auto;
  表空间已创建。
  #将logminer 的数据字典从system表空间转移到新建的表空间,防止撑满system表空间
  SQL> execute  dbms_logmnr_d.set_tablespace('tbs_stream');
  PL/SQL 过程已成功完成。
  #创建Stream管理用户
  SQL> create  user strmadmin identified by strmadmin default tablespace tbs_stream
  
temporary tablespace temp;
  用户已创建。
  #授权Stream管理用户
  SQL> grant  connect,resource,dba,aq_administrator_role to strmadmin;
  授权成功。
  SQL> begin
  
2
dbms_streams_auth.grant_admin_privilege(
  
3
grantee => 'strmadmin',
  
4
grant_privileges => true);
  
5
end;
  
6
/
  PL/SQL 过程已成功完成。
   
第四步:配置各自双方的数据库连接
     在source机器上添加dest数据源,名称为dest
  在dest机器上添加source数据源,名称为source
   
第五步:启用追加日志可以基于Database级别或Table级别,启用追加日志(Supplemental Log)。在建立根据Schema粒度进行复制的Oracle Stream 环境中,如果确认Schema 下所有Table 都有合理的主键(Primary Key),则不再需要启用追加日志。
     #启用Database 追加日志
  SQL> alter  database add supplemental log data;
  数据库已更改。
  #启用Table追加日志
  SQL> ALTER  DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE, FOREIGN KEY)
  
COLUMNS;
   
第六步:创建主数据库数据库链,以连接到从数据库
首先查看两台Oracle服务器的域名是否一致,如果不一致,需要alter database rename global_name to xxx
     SQL> select *  from global_name;
  GLOBAL_NAME
  --------------------------------------------------------------------------------
  SOURCE.REGRESS.RDBMS.DEV.US.ORACLE.COM
  SQL>conn  strmadmin/strmadmin;
  SQL> create  database link dest connect to strmadmin identified by strmadmin using 'dest';
  数据库链接已创建。
  SQL> select *  from tab@dest;
  未选定行
   
第七步:创建从数据库数据库链,以连接到主数据库
     SQL> select *  from global_name;
  GLOBAL_NAME
  --------------------------------------------------------------------------------
  DEST.REGRESS.RDBMS.DEV.US.ORACLE.COM
  SQL>conn  strmadmin/strmadmin
  SQL> create  database link source connect to strmadmin identified by strmadmin using  'source';
  数据库链接已创建。
  SQL> select *  from tab@source;
  未选定行
   
第八步:创建Master(源)流队列
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.set_up_queue(
  
3
queue_table => 'source_queue_table',
  
4
queue_name => 'source_queue');
  
5
end;
  
6
/
  PL/SQL 过程已成功完成。
   
第九步:创建Backup(目标)流队列
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.set_up_queue(
  
3
queue_table => 'dest_queue_table',
  
4
queue_name => 'dest_queue');
  
5
end;
  
6
/
  PL/SQL 过程已成功完成。
   
第十步:确保需要复制源机器上Schema对象的存在,并将Schema导出
     exp  userid=test/test@source file='e:/test.dmp' object_consistent=y rows=y
   
第十一步:将Schema对象导入到目标数据库上,如果不存在则创建相应的Schema,最好和源数据库各种属性保持一致,因为我这边莫名其妙发生了点错误。导致从数据库的流Apply进程为异常状态。
     imp  userid=test/test@dest file='e:/test.dmp' ignore=y commit=y log='e:/test.log' streams_instantiation=y  fromuser=test touser=test
   
第十二步:在master(源机器上)创建捕获进程
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.add_schema_rules(
  
3
schema_name => 'test',
  
4
streams_type => 'capture',
  
5
streams_name => 'capture_source',
  
6
queue_name => 'strmadmin.source_queue',
  
7
include_dml => true,
  
8
include_ddl => true,
  
9
include_tagged_lcr => false,
  
10
source_database => null,
  
11
inclusion_rule => true);
  
12
end;
  
13
/
  PL/SQL 过程已成功完成。
   
第十三步:在master(源机器上)创建传播进程
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.add_schema_propagation_rules(
  
3
schema_name => 'test',
  
4
streams_name => 'source_to_dest',
  
5
source_queue_name => 'strmadmin.source_queue',
  
6
destination_queue_name => 'strmadmin.dest_queue@dest',
  
7
include_dml => true,
  
8
include_ddl => true,
  
9
include_tagged_lcr => false,
  
10
source_database => 'source',
  
11
inclusion_rule => true);
  
12
end;
  
13
/
  PL/SQL 过程已成功完成。
  #修改propagation休眠时间为0,表示实时传播LCR
  SQL> begin
  
2
dbms_aqadm.alter_propagation_schedule(
  
3
queue_name => 'source_queue',
  
4
destination => 'dest',
  
5
latency => 0);
  
6
end;
  
7
/
  PL/SQL 过程已成功完成。
   
第十四步:在Backup(目标机器上)创建应用进程
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_streams_adm.add_schema_rules(
  
3
schema_name => 'test',
  
4
streams_type => 'apply',
  
5
streams_name => 'apply_dest',
  
6
queue_name => 'strmadmin.dest_queue',
  
7
include_dml => true,
  
8
include_ddl => true,
  
9
include_tagged_lcr => false,
  
10
source_database => 'source',
  
11
inclusion_rule => true);
  
12
end;
  
13
/
  PL/SQL 过程已成功完成。
   
第十五步:在Backup(目标机器上)启动Apply进程
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_apply_adm.start_apply(
  
3
apply_name => 'apply_dest');
  
4
end;
  
5
/
  PL/SQL 过程已成功完成。
   
第十六步:在Master(源机器上)启动Capture进程
     SQL> connect  strmadmin/strmadmin
  已连接。
  SQL> begin
  
2
dbms_capture_adm.start_capture(
  
3
capture_name => 'capture_source');
  
4
end;
  
5
/
  PL/SQL 过程已成功完成。
   


  




====================
哥们,你测试过在 source 库上每次 delete 500万或者更多的数据的时候,对数据库的性能的影响  ??????????????????????
作者: 五“宅”一生    时间: 2008-12-22 15:54
好帖子。支持!
作者: networksway    时间: 2008-12-22 15:59
study
作者: c@ini@o    时间: 2008-12-22 16:05
学习中... 支持一下
作者: liyongdong    时间: 2008-12-23 13:10
学习中.
作者: qqdan3    时间: 2008-12-23 14:16
本周回去做个实验,谢谢
作者: zh_lg    时间: 2008-12-23 14:29

楼主要把自己拖到火坑了!
如果能保证你们系统large txn比较少!那还成,否则等着别人叫吧。
作者: wuxunhym    时间: 2008-12-23 18:07
原帖由 wenaini 于 2008-12-22 09:31 发表

想要晚上被频繁电话问候可以用用,我测试到最高的版本是10204。。。。。。。。。。。。。。bug起码10+,而且oracle推荐的补丁已经全部打过鸟


后来是怎么解决的呢??
作者: ochef    时间: 2008-12-24 15:10
學習,回去做做實驗
作者: tingsheng    时间: 2008-12-24 17:05
bug是挺多的,最好不要在生产环境中用
作者: lsl031    时间: 2009-2-10 11:06
谢谢共享!
作者: sunchao    时间: 2009-2-10 11:18
不错
作者: joebinl    时间: 2009-2-10 11:32
楼主辛苦,学习一下。
作者: ab5669    时间: 2009-11-17 10:23
好文档, 多谢楼主分享




欢迎光临 ITPUB论坛-专业的IT技术社区 (http://www.itpub.net/) Powered by Discuz! X3.2