oracle 高级复制同步表数据
<div> <strong><span style="font-size:small;">oracle 高级复制同步数据</span></strong> </div> <div> oracle我不是很熟,但现被安排要做个2台数据库表同步复制,不懂,只能从开始研究,制作。如果你和我一样,看了我的制作过程,一定给你很大的帮助。废话不说了,开始.......google....次数已经记不清楚了,可以用天衡量了,大概时断时续一周。。汗死。。。。。在此,非常感谢那些发表文章的人,通过看过很多人的文章,我才能基本完成,感谢! <br /> <strong>概述</strong>: <br /> 在Internet上运作数据库经常会有这样的需求:把遍布全国各城市相似的数据库应用统一起来,一个节点的数据改变不仅体现在本地,还反映到远端。复制技术给用户提供了一种快速访问共享数据的办法。 <br /> <strong>前提条件</strong> <br /> 要准备2台测试用的机器,开始制作如下: <br /> 2台机器安装oracle10g,注意我的版本相同。 <br /> SID都是music1 <br /> 1:安装及运行vnc。。。用于远程安装oracle <br /> 2:安装及运行 oracle10.2.... <br /> 完成以上步骤后,基本工作就算做完了,现在开始配置高级复制。 <br /> 假设数据库机器为 数据库机器A ...数据库机器B... <br /> 数据库机器A地址为;192.168.1.205 <br /> SID:music1 <br /> 域名:master.anymusic.com <br /> 数据库机器B地址为;192.168.1.226 <br /> SID:music1 <br /> 域名:salse.anymusic.com <br /> 首先配置确认俩台机器可以互相访问,如下: <br /> <strong>机器A操作:</strong> <br /> 用oracle登陆 <br /> 修改如下文件; <br /> vi tnsnames.ora <br /> 添加: <br /> MUSIC226 = 这个名称随便起 <br /> (DE.ION = <br /> (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.226)(PORT = 1521)) 这里为机器B的地址及数据库端口号 <br /> (CONNECT_DATA = <br /> (SERVER = DEDICATED) <br /> (SERVICE_NAME = music1) 这个名称为机器B 数据库SID的值 <br /> ) <br /> ) <br /> 配置完重起数据库 </div> <div> <strong>机器B操作:</strong> <br /> 用oracle登陆 <br /> 同样修改如下文件; <br /> vi tnsnames.ora <br /> 添加: <br /> MUSIC205 = 这个名称随便起 <br /> (DE.ION = <br /> (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.205)(PORT = 1522)) 这里为机器A的地址及数据库端口号 <br /> (CONNECT_DATA = <br /> (SERVER = DEDICATED) <br /> (SERVICE_NAME = music1) 这个名称为机器A 数据库SID的值 <br /> ) <br /> ) <br /> 重起数据库 <br /> 测试数据库连通性,在机器A如下; <br /> [oracle <a class="referer" href="/misc/goto?guid=4959499949691259705" target="_blank">@localhost</a> admin]$ tnsping music226 <br /> 显示如下; <br /> TNS Ping Utility for Linux: Version 10.2.0.1.0 - Production . 04-JAN-2009 16:53:23 </div> <div> Copyright (c) 1997, 2005, Oracle. All rights reserved. </div> <div> Used parameter files: <br /> /home/oracle/oracle/product/10.2.0/network/admin/sqlnet.ora </div> <div> <br /> Used TNSNAMES adapter to resolve the alias <br /> Attempting to contact (DE.ION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.226)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = music1))) <br /> OK (10 msec) <br /> <br /> 测试数据库连通性,在机器B如下; <br /> [oracle <a class="referer" href="/misc/goto?guid=4959499949691259705" target="_blank">@localhost</a> admin]$ tnsping music205 <br /> 显示; <br /> TNS Ping Utility for Linux: Version 10.2.0.1.0 - Production . 04-JAN-2009 17:09:04 </div> <div> Copyright (c) 1997, 2005, Oracle. All rights reserved. </div> <div> Used parameter files: <br /> /home/oracle/oracle/product/10.2.0/network/admin/sqlnet.ora </div> <div> Used TNSNAMES adapter to resolve the alias <br /> Attempting to contact (DE.ION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.205)(PORT = 1522)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = music1))) <br /> OK (0 msec) </div> <div> 注意:这里我的2台机器没有加防火墙等其他安全措施,数据库也没有设置限制地址登陆。如果你连接不上,就仔细看看自己的其他配置。 </div> <div> <strong>接着在机器A操作如下:</strong> <br /> 察看v$option,Advanced replication为TRUE,则支持高级复制功能;否则不支持 <br /> select * from v$option; <br /> 以上察看结果默认为ture,支持高级复制。 </div> <div> 察看global_name参数 <br /> SQL> show parameter global_name; <br /> NAME TYPE VALUE <br /> ------------------------------------ ----------- ------------------------------ <br /> global_names boolean FALSE <br /> 看过大多数文章都将这里要设置成true,我没有改动,默认false使用, </div> <div> <br /> 察看默认global_name,数据库域名 <br /> SQL> select * from global_name; <br /> GLOBAL_NAME <br /> -------------------------------------------------------------------------------- <br /> MUSIC1.REGRESS.RDBMS.DEV.US.ORACLE.COM </div> <div> 修改global_name,数据库域名 <br /> SQL> alter database rename global_name to master.anymusic.com; <br /> 察看修改结果; <br /> SQL> select * from global_name; <br /> GLOBAL_NAME <br /> -------------------------------------------------------------------------------- <br /> MASTER.ANYMUSIC.COM </div> <div> 创建帐户及数据: <br /> SQL> create user wcms identified by abc123 default tablespace users; <br /> SQL>grant connect,resource to wcms; <br /> 切换到wcms, <br /> SQL> conn wcms/abc123 <br /> 创建表 <br /> SQL> create table test(id number,name varchar2(20),constraint test_id_pk primary key(id)); (主键一定是要的); <br /> 插入数据 <br /> SQL> insert into test values(1,'abc'); <br /> SQL> insert into test values(2,'def'); <br /> 建立管理数据库复制的用户repadmin,并赋权。 <br /> SQL> create user repadmin identified by repadmin default tablespace users temporary tablespace temp; <br /> SQL> execute dbms_defer_sys.register_propagator('repadmin'); <br /> SQL> grant execute any procedure to repadmin; <br /> SQL> execute dbms_repcat_admin.grant_admin_any_repgroup('repadmin'); <br /> SQL> execute dbms_repcat_admin.grant_admin_any_schema(username => 'repadmin'); <br /> SQL> grant comment any table to repadmin; <br /> SQL> grant lock any table to repadmin; <br /> SQL> grant select any dictionary to repadmin; <br /> 用repadmin 创建database link 连接 <br /> SQL> conn repadmin/repadmin <br /> SQL> create database link "salse.anymusic.com" connect to repadmin identified by repadmin using 'music226'; <br /> 说明一下;salse.anymusic.com为我修改global_name的值 <br /> music226 :是以上tnsnames.ora中我设定连接机器B数据库的值 <br /> 察看一下:SQL> select owner,db_link,host from all_db_links; <br /> OWNER DB_LINK HOST </div> <div> REPADMIN SALSE.ANYMUSIC.COM music226 </div> <div> <br /> <strong>在机器B操作如下;</strong> <br /> 察看v$option,Advanced replication为TRUE,则支持高级复制功能;否则不支持 <br /> select * from v$option; <br /> 以上察看结果默认为ture,支持高级复制。 <br /> 察看global_name参数 <br /> SQL> show parameter global_name; <br /> NAME TYPE VALUE <br /> ------------------------------------ ----------- ------------------------------ <br /> global_names boolean FALSE </div> <div> 察看默认global_name,数据库域名 <br /> SQL> select * from global_name; <br /> GLOBAL_NAME <br /> -------------------------------------------------------------------------------- <br /> MUSIC1.REGRESS.RDBMS.DEV.US.ORACLE.COM <br /> 修改global_name,数据库域名 <br /> SQL> alter database rename global_name to salse.anymusic.com; <br /> 察看修改结果; <br /> SQL> select * from global_name; <br /> GLOBAL_NAME <br /> -------------------------------------------------------------------------------- <br /> SALSE.ANYMUSIC.COM </div> <div> 创建帐户及数据: <br /> SQL> create user wcms identified by abc123 default tablespace users; <br /> SQL>grant connect,resource to wcms; <br /> 切换到wcms, <br /> SQL> conn wcms/abc123 <br /> 创建表 <br /> SQL> create table test(id number,name varchar2(20),constraint test_id_pk primary key(id)); (主键一定是要的); <br /> 插入数据 <br /> SQL> insert into test values(1,'zhao'); <br /> SQL> insert into test values(2,'yong'); <br /> 配置复制管理用户 <br /> SQL> create user repadmin identified by repadmin default tablespace users; <br /> 建立管理数据库复制的用户repadmin,并赋权。 <br /> SQL> create user repadmin identified by repadmin default tablespace users temporary tablespace temp; <br /> SQL> execute dbms_defer_sys.register_propagator('repadmin'); <br /> SQL> grant execute any procedure to repadmin; <br /> SQL> execute dbms_repcat_admin.grant_admin_any_repgroup('repadmin'); <br /> SQL> execute dbms_repcat_admin.grant_admin_any_schema(username => 'repadmin'); <br /> SQL> grant comment any table to repadmin; <br /> SQL> grant lock any table to repadmin; <br /> SQL> grant select any dictionary to repadmin; <br /> 用repadmin 创建database link 连接 <br /> SQL> create database link "master.anymusic.com" connect to repadmin identified by repadmin using 'music205'; <br /> 说明一下;master.anymusic.com为我修改global_name的值 <br /> music205 :是以上tnsnames.ora中我设定连接机器A数据库的值 <br /> 察看一下:SQL> select owner,db_link,host from all_db_links; <br /> SQL> select owner,db_link,host from all_db_links; <br /> OWNER DB_LINK HOST <br /> -------------------------------------------------------------------------------- <br /> REPADMIN MASTER.ANYMUSIC.COM music205 </div> <div> 测试开始 <br /> 登陆机器A <br /> 测试数据库链接: <br /> SQL> select * from <a href="/misc/goto?guid=4959499949783953521" rel="nofollow">global_name@salse.anymusic.com</a>; <br /> 显示: <br /> GLOBAL_NAME <br /> -------------------------------------------------------------------------------- <br /> SALSE.ANYMUSIC.COM <br /> 表示数据库到此连接成功 </div> <div> 登陆机器B <br /> 测试数据库链接: <br /> SQL> select * from <a href="/misc/goto?guid=4959499949861760159" rel="nofollow">global_name@master.anymusic.com</a>; <br /> 显示: <br /> GLOBAL_NAME <br /> -------------------------------------------------------------------------------- <br /> MASTER.ANYMUSIC.COM <br /> 表示数据库到此连接成功。 </div> <div> 登陆数据库机器A <br /> 开始复制实施进程,在主数据库执行 <br /> 用repadmin 登陆数据库 <br /> 创建主复制组rep_anymusic,此名可以任意命名 <br /> SQL> execute dbms_repcat.create_master_repgroup('REP_anymusic'); <br /> 察看复制主体组相关信息: <br /> SQL> select gname,master,status from dba_repgroup <br /> GNAME M STATUS <br /> ------------------------------ - --------- <br /> REP_ANYMUSIC Y QUIESCED <br /> QUIESCED表示主体组未开始运行。 <br /> 在主体组中添加复制对象 <br /> SQL> execute dbms_repcat.create_master_repobject (sname=>'wcms',oname=>'test', type=>'TABLE', use_existing_object=>true,gname=>'REP_anymusic',copy_rows=>true); <br /> sname 实现数据库复制的用户名称 <br /> oname 实现数据库复制的数据库对象名称 <br /> type 实现数据库复制的数据库对象类别。(支持的类别:表,索引,同义词,触发器,视图,过程,函数,程序包,程序包体) <br /> use_existing_object true表示用主复制节点已经存在的数据库对象 <br /> gname 主复制组名 <br /> copy_rows true表示第一次开始复制时和主复制节点保持一致 </div> <div> 察看复制主体组中复制对象的相关信息: <br /> SQL>select sname,oname,status,gname from dba_repobject <br /> SNAME ONAME STATUS GNAME <br /> ------------------------------ <br /> WCMS TEST VALID REP_ANYMUSIC <br /> 为复制对象生成复制支持: <br /> SQL> execute dbms_repcat.generate_replication_support('wcms','test','TABLE'); <br /> (说明:产生支持wcms用户下test表复制的数据库触发器和程序包) <br /> 再次察看对应的复制对象的相关信息: <br /> SQL> select sname,oname,status,gname from dba_repobject </div> <div> SNAME ONAME STATUS GNAME <br /> ------------------------------ <br /> WCMS TEST VALID REP_ANYMUSIC </div> <div> WCMS TEST$RP VALID REP_ANYMUSIC </div> <div> WCMS TEST$RP VALID REP_ANYMUSIC </div> <div> 为复制主体组添加数据库主站点: <br /> SQL>execute dbms_repcat.add_master_database(gname=>'REP_anymusic',master=>'salse.anymusic.com', </div> <div> use_existing_objects=>true,copy_rows=>true, propagation_mode => 'synchronous'); <br /> gname 主复制组名 <br /> master 加入主复制节点的另一个数据库 <br /> use_existing_object true表示用主复制节点已经存在的数据库对象 <br /> copy_rows false表示第一次开始复制时不用和主复制节点保持一致 <br /> propagation_mode 异步地执行 <br /> 察看复制站点信息: <br /> SQL> select gname,dblink,masterdef,master from dba_repsites <br /> GNAME DBLINK M M <br /> REP_ANYMUSIC MASTER.ANYMUSIC.COM Y Y <br /> REP_ANYMUSIC SALSE.ANYMUSIC.COM N Y <br /> 启动复制进程: <br /> SQL> execute dbms_repcat.resume_master_activity('REP_anymusic',true); </div> <div> 再次察看复制主体组相关信息: <br /> SQL> select gname,master,status from dba_repgroup </div> <div> GNAME M STATUS <br /> ------------------------------ - --------- <br /> REP_ANYMUSIC Y NORMAL <br /> 确认复制的任务队列已经加入数据库的数据字典 <br /> SQL>select job,log_user,this_date,next_date,next_sec,broken,failures,what from user_jobs; <br /> JOB LOG_USER THIS_DATE NEXT_DATE </div> <div> NEXT_SEC B FAILURES WHAT <br /> 21 REPADMIN 05-JAN-09 </div> <div> 14:23:42 N 0 dbms_repcat.do_deferred_repcat_admin('"REP_ANYMUSIC"', FALSE); <br /> 注释:job:表示当前此工作的标示号 <br /> log_user: 表示当前工作的操作者 <br /> this_date:表示当前工作是否正在工作,空为空闲。 <br /> next_date:表示此工作下次执行日期 <br /> next_sec:表示此工作下次执行时间 <br /> broken:表示工作是否被挂起 <br /> failures:表示工作失败次数 <br /> what: 应该是工作执行语句 <br /> 注意:复制主体组的状态由QUIESCED变为NORMAL。停顿(quiesced )正常(normal) <br /> 这里在以repadmin登陆机器B,察看结果如下就表示正确 <br /> SQL>select job,log_user,this_date,next_date,next_sec,broken,failures,what from user_jobs; <br /> JOB LOG_USER THIS_DATE NEXT_DATE NEXT_SEC B FAILURES WHAT <br /> 21 REPADMIN 05-JAN-09 14:52:04 N 0 dbms_repcat.do_deferred_repcat_admin('"REP_ANYMUSIC"', FALSE); </div> <div> 至此,这个复制过程实施完毕。可以进行相关的数据操作进行测试 <br /> 开始测试: <br /> <strong>用wcms登陆机器A数据库</strong> <br /> 插入表test中数据 <br /> SQL> insert into test values(4,'aaaaaaaa'); <br /> 察看结果 <br /> SQL> select * from test; <br /> ID NAME <br /> ---------- -------------------- <br /> 4 aaaaaaaa <br /> 用wcms登陆机器B数据库 <br /> 察看表test中数据,因为我以上只对表test作了数据同步工作 <br /> SQL> select * from test; <br /> ID NAME <br /> ---------- -------------------- <br /> 4 aaaaaaaa <br /> 如果没有看到同步的数据,那就多等会,再看。 <br /> 由于以上只同步一张表,在现有组中再次插入同步的表, <br /> 以wcms 登陆数据库,在机器A中创建表 <br /> SQL> create table aa(id number,name varchar2(20),constraint aa_id_pk primary key(id)); <br /> 接着插入数据 <br /> SQL> insert into aa values(1,'abc'); <br /> 以repadmin登陆数据库 <br /> <br /> 接下来添加新表然后执行同步操作 <br /> SQL> execute dbms_repcat.suspend_master_activity('rep_anymusic'); <br /> 取消抑制。停止主体组 <br /> SQL> execute dbms_repcat.create_master_repobject(sname=>'wcms',oname=>'aa',type=>'TABLE',use_existing_object=>true,gname=>'REP_anymusic',copy_rows=>true); <br /> 为组增加新表。 <br /> SQL>execute dbms_repcat.generate_replication_support('wcms','aa','TABLE') <br /> 增加支持。 <br /> SQL>execute dbms_repcat.resume_master_activity('REP_anymusic',true); <br /> 启动进程 <br /> <strong>用wcms帐户登陆机器B,</strong> <br /> SQL> select * from aa; <br /> ID NAME <br /> ---------- -------------------- <br /> 1 abc <br /> <strong>登陆机器A</strong> <br /> 创建复制数据库的时间表,作用是将俩个数据库添加到主体组的表同步,包括,添加,删除,创建 新表及表中数据。以上作用说明我是个人认为。如果你清楚以下push任务具体作用,请告诉我。。 <a href="https://simg.open-open.com/show/92428b2166257663aa7369fe8a7219af.gif" target="_blank"><img style="cursor:pointer;" alt="" src="https://simg.open-open.com/show/92428b2166257663aa7369fe8a7219af.gif" width="19" height="19" /></a> <br /> 添加PUSH任务 <br /> SQL> begin <br /> 2 dbms_defer_sys.schedule_push( <br /> 3 destination=>'SALSE.ANYMUSIC.COM', <br /> 4 interval=>'sysdate + 10/1440', 一天每10分钟运行一次 <br /> 5 next_date=>sysdate, 下一次运行时间为当前时间 <br /> 6 delay_seconds=>50, 延迟秒数50 <br /> 7 parallelism=>1); <br /> 8 end; <br /> 9 / <br /> 如果出现以下类似错误,那就注意仔细看看语法是否正确,我出现这个错误是,第3行,第4行 没有加单引号出的错。哈哈 <br /> ERROR at line 3: <br /> ORA-06550: line 3, column 16: <br /> PLS-00201: identifier 'SALSE.ANYMUSIC' must be declared <br /> ORA-06550: line 2, column 1: <br /> PL/SQL: Statement ignored </div> <div> ERROR at line 1: <br /> ORA-23319: parameter value "07-JAN-09" is not appropriate <br /> ORA-06512: at "SYS.DBMS_DEFER_SYS", line 2346 <br /> ORA-01403: no data found <br /> ORA-06512: at line 2 </div> <div> 添加PURGE任务 <br /> SQL> begin <br /> 2 dbms_defer_sys.schedule_purge ( <br /> 3 next_date => sysdate, <br /> 4 interval => 'sysdate + 10/1440', <br /> 5 delay_seconds => 0); <br /> ### 6 rollback_segment =>0); <br /> 7 end; <br /> 8 / </div> <div> SQL> select job,what from user_jobs; </div> <div> JOB WHAT <br /> 21 dbms_repcat.do_deferred_repcat_admin('"REP_ANYMUSIC"', FALSE); </div> <div> 41 declare rc binary_integer; begin rc := sys.dbms_defer_sys.push(destination=>'SALSE.ANYMUSIC.COM'); end; </div> <div> 42 declare rc binary_integer; begin rc := sys.dbms_defer_sys.purge( delay_seconds=>0, rollback_segment=>'0'); end; </div> <div> <strong>登陆机器B:</strong> <br /> 用repadmin登陆数据库,同样添加以下代码 <br /> SQL> begin <br /> 2 dbms_defer_sys.schedule_push( <br /> 3 destination=>'master.anymusic.com', <br /> 4 interval=>'sysdate + 10/1440', <br /> 5 next_date=>sysdate, <br /> 6 delay_seconds=>50, 延迟秒数50 <br /> 7 parallelism=>1); <br /> 8 end; <br /> 9 / </div> <div> SQL> begin <br /> 2 dbms_defer_sys.schedule_purge ( <br /> 3 next_date => sysdate, <br /> 4 interval => 'sysdate + 10/1440', <br /> 5 delay_seconds => 0); <br /> ### 6 rollback_segment =>0); <br /> 7 end; <br /> 8 / <br /> SQL> select job,what from user_jobs; </div> <div> JOB WHAT <br /> -------------------------------------------------------------------------------- <br /> 21 dbms_repcat.do_deferred_repcat_admin('"REP_ANYMUSIC"', FALSE); </div> <div> 41 declare rc binary_integer; begin rc := sys.dbms_defer_sys.push(destination=>'MASTER.ANYMUSIC.COM'); end; </div> <div> 42 declare rc binary_integer; begin rc := sys.dbms_defer_sys.purge( delay_seconds=>0, rollback_segment=>'0'); end; </div> <div> </div> <div> OK!!!!至此完成同步复制操作,以下是一些实用命令,呵呵呵。。如果以上有哪里不对,请给于指明。。。。。。。 </div> <div> ####################################### <br /> 用select * from dba_repgroup;检查站点状态 状态为NORMAL时表示该站点正常。 <br /> 相关视图 <br /> " DBA_REPSITES ----复制站点情况 <br /> " DBA_REPGROUP -----复制组情况 <br /> " DBA_REPOBJECT ----复制对象情况 <br /> " DBA_REPCATLOG ---同步情况日志 <br /> ###################################### <br /> 如果想删除其中的一个同步表,如下执行; <br /> SQL> execute dbms_repcat.suspend_master_activity('rep_anymusic'); 停止主体组 <br /> SQL> EXECUTE Dbms_Repcat.Drop_Master_Repobject('wcms','test','table'); 删除同步表 <br /> SQL> EXECUTE Dbms_Repcat.Remove_Master_Databases('rep_anymusic', 'master.anymusic.com');删除主站点上面的组 <br /> SQL> execute dbms_repcat.resume_master_activity('REP_anymusic',true); 启动复制组 <br /> ###################################### <br /> 删除私有数据链路 <br /> 用repadmin 登陆数据库 <br /> EXECUTE Dbms_Repcat.Drop_Master_Repgroup('主体组名');删除主体组 <br /> DROP DATABASE LINK master.anymusic.com; 删除db link名 <br /> 删除jobs <br /> select job,what from user_jobs; 查询job numbers <br /> EXECUTE Dbms_Job.Remove(2); 括号内填写刚查询到的job numbers <br /> ###################################### <br /> 删除REPADMIN用户,注意:必须先删除站点下隶属于该repadmin用户的jobs和组mygrp 才能删除用户 <br /> 用sys登陆 <br /> EXECUTE Dbms_Defer_Sys.Unregister_Propagator(username=>'REPADMIN'); <br /> EXECUTE Dbms_Repcat_Admin.Revoke_Admin_Any_Schema(username=>'REPADMIN'); <br /> DROP USER repadmin CASCADE; <br /> ###################################### <br /> --删除公用的数据链路 <br /> 用sys登陆 <br /> DROP PUBLIC DATABASE LINK master.anymusic.com; <br /> ###################################### <br /> 备注:每次运行完repcat 包以后都应该执行一次commit,因为某些rep 的存储过程是不会 <br /> 自动commit 的,同时这也是一个troubleshooting,一般的rep 脚本都会较快的返回结果, <br /> 如果一条命令之后长时间没有结果返回,那么很可能是上面的命令没有commit,取消掉当 <br /> 前的命令,然后作一次commit,再重新执行,一般都能够解决问题。 <br /> ####################################### <br /> 强制删除复制组 <br /> Sql>Truncate table system.def$_aqcall; <br /> Sql>Exec dbms_repcat.drop_master_repgroup(gname=>'mygrp',all_sites=>true); <br /> ######################################## </div> <div> </div> <div> 出处 <a href="/misc/goto?guid=4959499949946756211" rel="nofollow">http://zhaoyong.blog.51cto.com/61971/125470</a> </div>
本文由用户 jopen 自行上传分享,仅供网友学习交流。所有权归原作者,若您的权利被侵害,请联系管理员。
转载本站原创文章,请注明出处,并保留原始链接、图片水印。
本站是一个以用户分享为主的开源技术平台,欢迎各类分享!