原理是:
Use the RMAN DUPLICATE command to create a duplicate database using target database backups.
通过RMAN用目标数据库的备份来创建duplicate database
什么是duplicate database:
A duplicate database is a copy of the target database (or a subset of the target database) with a new, unique database identifier (DBID). The target database site and duplicate database site can be on the same or separate hosts. The duplicate database is created using backups and archived redo log files from the target database.
具体的创建步骤如下:
The step of creating a duplicate database:
1,Create an Oracle password file for the auxiliary instance.
2,Establish Oracle Net connectivity to the auxiliary instance.
3,Create an initialization parameter file for the auxiliary instance.
4,Start the auxiliary instance in NOMOUNT mode.
5,Mount or open the target database.
6,Ensure that backups and archived redo log files are available.
7,Allocate auxiliary channels if needed.
8,Execute the DUPLICATE command.
Understanding the RMAN Duplication Operation:
了解RMAN在创建duplicate database的时候具体的做了那些操作:
When you execute the DUPLICATE command, RMAN performs the following operations:
1,Creates a control file for the duplicate database
2,Restores the target datafiles to the duplicate database
3,Performs incomplete recovery using all available incremental backups and archived redo log files
4,Shuts down and restarts the auxiliary instance
5,Opens the duplicate database with the RESETLOGS option
6,Creates the online redo log files
7,Generates a new, unique database identifier (DBID) for the duplicate database
我下面的实验是在同一台host上做的duplicate.
vi /etc/hosts里面DB HOST IP要和Listener.ora里的IP一样
创建目录:
[oracle@even ~]$ mkdir /u01/app/oracle/oradata/testdup
[oracle@even test]$ mkdir -p /u01/app/oracle/admin/testdup/{a,b,c,dp,u}dump
启动监听:
[oracle@even dbs]$ lsnrctl start
创建复制数据库时所使用的初始化参数inittestdup.ora:
$ cd $ORACLE_HOME/dbs
[oracle@even dbs]$ vi inittestdup.ora
db_name=testdup
db_block_size=8192
CONTROL_FILES='/u01/app/oracle/oradata/testdup/control01.ctl', '/u01/app/oracle/oradata/testdup/control02.ctl','/u01/app/oracle/oradata/testdup/control03.ctl'
undo_management=auto
undo_tablespace=undotbs1
#下面路径要成对的出现
db_file_name_convert='/u01/app/oracle/oradata/test','/u01/app/oracle/oradata/testdup'
log_file_name_convert='/u01/app/oracle/oradata/test','/u01/app/oracle/oradata/testdup'
#目标和源版本一致
compatible=10.2.0.1.0
shared_pool_size=200M
sga_target=500M
配置tnsnames:
cd $ORACLE_HOME/network/admin
[oracle@even admin]$ vi tnsnames.ora
TEST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = even.oracle.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = test)
)
)
TESTDUP =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = even.oracle.com)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = testdup)
)
)
配置监听:
cd $ORACLE_HOME/network/admin
[oracle@even admin]$ vi listener.ora
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = even.oracle.com)(PORT = 1521))
)
)
SID_LIST_LISTENER=
(SID_LIST=
(SID_DESC=
(GLOBAL_DBNAME=test)
(ORACLE_HOME=/u01/app/oracle/product/10.2.0/db_1)
(SID_NAME=test)
)
(SID_DESC=
(GLOBAL_DBNAME=testdup)
(ORACLE_HOME=/u01/app/oracle/product/10.2.0/db_1)
(SID_NAME=testdup)
)
)
重新加载监听:
[oracle@even admin]$ lsnrctl reload
配置密码文件
cd $ORACLE_HOME/dbs
orapwd file=orapwtestdup password=oracle entries=5
[oracle@even ~]$ sqlplus sys/oracle@testdup as sysdba
SQL*Plus: Release 10.2.0.1.0 - Production on Mon Dec 31 16:15:01 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup nomount pfile='$ORACLE_HOME/dbs/inittestdup.ora'
ORACLE instance started.
Total System Global Area 524288000 bytes
Fixed Size 1220360 bytes
Variable Size 218104056 bytes
Database Buffers 301989888 bytes
Redo Buffers 2973696 bytes
[oracle@even ~]$ export ORACLE_SID=testdup
[oracle@even ~]$ rman target sys/oracle@test auxiliary /
Recovery Manager: Release 10.2.0.1.0 - Production on Mon Dec 31 16:26:32 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
connected to target database: TEST (DBID=2101363784)
connected to auxiliary database: TESTDUP (not mounted)
注意在做duplicate 是恢复到最后一个归档的时间点,所以一定要有归档日志,即duplicate之前一定还要切换几下日志,否则有可能会duplicate 不成功。
会提示unable to find archive log
SQL> alter system switch logfile;
System altered.
RMAN>run{
allocate auxiliary channel c1 device type disk;
allocate auxiliary channel c2 device type disk;
duplicate target database to testdup;
}
contents of Memory Script:
{
Alter clone database open resetlogs;
}
executing Memory Script
database opened
Finished Duplicate Db at 2012-12-31 16:48:54
表示duplicate数据库成功!!!!
再创建一个spfile,让数据库根据spfile启动。
[oracle@even ~]$ sqlplus / as sysdba
SQL*Plus: Release 10.2.0.1.0 - Production on Mon Dec 31 16:53:51 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining options
SQL> select status,instance_name from v$instance;
STATUS INSTANCE_NAME
------------------------ --------------------------------
OPEN testdup
SQL> create spfile from pfile;
File created.
到此duplicate 数据库顺利完成。。。
什么是主键:
表中经常有一个列或列的组合,其值能唯一地标识表中的每一行。这样的一列或多列称为表的主键,通过它可强制表的实体完整性。当创建或更改表时可通过定义 PRIMARY KEY 约束来创建主键。一个表只能有一个 PRIMARY KEY 约束,而且 PRIMARY KEY 约束中的列不能接受空值。由于 PRIMARY KEY 约束确保唯一数据,所以经常用来定义标识列。
作用:
1)保证实体的完整性;
2)加快数据库的操作速度
3) 在表中添加新记录时,mysql会自动检查新记录的主键值,不允许该值与其他记录的主键值重复。
4) mysql自动按主键值的顺序显示表中的记录。如果没有定义主键,则按输入记录的顺序显示表中的记录。
主键的必要性:
有些朋友可能不提倡数据库表必须要主键,但在我的思考中,觉得每个表都应该具有主键,不管是单主键还是双主键,主键的存在就代表着表结构的完整性,表的记录必须得有唯一区分的字段,主键主要是用于其他表的外键关联,本记录的修改与删除,当我们没有主键时,这些操作会变得非常麻烦。
主键的无意义性:
我强调主键不应该具有实际的意义,这可能对于一些朋友来说不太认同,比如订单表吧,会有“订单编号”字段,而这个字段呢在业务实际中本身就是应该具有唯一性,具有唯一标识记录的功能,但我是不推荐采用订单编号字段作为主键的,因为具有实际意义的字段,具有“意义更改”的可能性,比如订单编号在刚开始的时候我们一切顺利,后来客户说“订单可以作废,并重新生成订单,而且订单号要保持原订单号一致”,这样原来的主键就面临危险了。因此,具有唯一性的实际字段也代表可以作为主键。因此,我推荐是新设一个字段专门用为主键,此主键本身在业务逻辑上不体现,不具有实际意义。而这种主键在一定程序增加了复杂度,所以要视实际系统的规模大小而定,对于小项目,以后扩展不会很大的话,也查允许用实际唯一的字段作主键的。
主键的选择
①编号作主键 此方法就是采用实际业务中的唯一字段的“编号”作为主键设计,这在小型的项目中是推荐这样做的,因为这可以使项目比较简单化,但在使用中却可能带来一些麻烦,比如要进行“编号修改”时,可能要涉及到很多相关联的其他表,就像黎叔说的“后果很严重”;还有就是上面提到的“业务要求允许编号重复时”,我们再那么先知,都无法知道业务将会修改成什么?
②自动编号主键 这种方法也是很多朋友在使用的,就是新建一个ID字段,自动增长,非常方便也满足主键的原则,优点是:数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利;数字型的,占用空间小,易排序,在程序中传递也方便;如果通过非系统增加记录(比如手动录入,或是用其他工具直接在表里插入新记录,或老系统数据导入)时,非常方便,不用担心主键重复问题。 缺点:其实缺点也就是来自其优点,就是因为自动增长,在手动要插入指定ID的记录时会显得麻烦,尤其是当系统与其他系统集成时,需要数据导入时,很难保证原系统的ID不发生主键冲突(前提是老系统也是数字型的);如果其他系统主键不是数字型那就麻烦更大了,会导致修改主键数据类型了,这也会导致其他相关表的修改,后果同样很严重;就算其他系统也是数字型的,在导入时,为了区分新老数据,可能想在老数据主键前统一加一个“o”(old)来表示这是老数据,那么自动增长的数字型又面临一个挑战。
③Max加一 由于自动编号存在那些问题,所以有些朋友就采用自己生成,同样是数字型的,只是把自动增长去掉了,采用在Insert时,读取Max值后加一,这种方法可以避免自动编号的问题,但也存在一个效率问题,如果记录非常大的话,那么Max()也会影响效率的;更严重的是并发性问题,如果同时有两人读到相同的Max后,加一后插入的ID值会重复,这已经是有经验教训的了。
④自制加一 考虑Max加一的效率后,有人采用自制加一,也就是建一个特别的表,字段为:表名,当前序列值。这样在往表中插入值时,先从此表中找到相应表的最大值后加一,进行插入,有人可能发现,也可能会存在并发处理,这个并发处理,我们可以采用lock线程的方式来避免,在生成此值的时,先Lock,取到值以后,再unLock出来,这样不会有两人同时生成了。这比Max加一的速度要快多了。但同样存在一个问题:在与其他系统集成时,脱离了系统中的生成方法后,很麻烦保证自制表中的最大值与导入后的保持一致,而且数字型都存在上面讲到的“o”老数据的导入问题。因此在“自制加一”中可以把主键设为字符型的。字符型的自制加一我倒是蛮推荐的,应该字符型主键可以应付很多我们意想不到的情况。
Sql Server :
Sql代码
MYSQL查询前10条的方法(limit参数的第一个参数n(如下面的0或1)表示前n条记录是不在选择范围内,相当于hibernate的setFirstResult的参数加一;第二个参数表示要选择的记录条数,相当于hibernate的setMaxResult的参数):
MySQL查询前5条方法(假设一个表为users表,这里作为子查询时要加入别名不然会出错,还有一点要注意的是order by在limit前面,不然还没出结果前就说要前几条,怎么搞嘛,所以limit要放最后。):
ORACLE查询前十条的方法: