这次,我们将在Linux下来动手完成Oracle数据库的安装与使用。
Oracle本身是可以免费下载的包括 它的企业版以及被它收购的Weblogic和Sun中的几乎任何东西你都可以拿来下载和使用,不像IBM和Tibco一些其它厂商,只有“试用版”给你下载,Oracle的东西没有时间限制,你拿来做练习,搭实验环境都是没有任何的问题的。
但是,如果你出了问题,需要用到Oracle的补丁或者是Oracle的技术支持,这就开始收费。
Oracle就是这种“卖Service”的模式。
还有就是你安装了Oracle后,你的应用是给另一家企业用的或者是带有商业用途,那对不起Oracle也会问你来收费。
在linux下安装oracle是一件令人生畏的事情,其复杂程度远远超过安装linux操作系统本身。如果能够进行成功的安装oracle,那么同时也就顺便掌握了linux一些技术。
本文介绍在redhat linux 下安装oracle 10g 的方法。在这里说明一下,Oracle 10g的g是grid 的缩写,意为网格,目前较为前沿的网络计算技术。
这次我们将在Linux环境下安装Oracle,对Oracle支持最好的莫过于SuSe Linux,但是随着后来RedHat走向了商业化后,RedHat与Oracle公司开始形成一种密切的关系,因此如果你手上有RedHat As 5.5x及以下版本或者是Fedora14及以上版本话那是最好不过了。
Oracle下载地址:进入下载
打开一个Terminal窗口
进入到你的jdk下载的目录下并输入:
./jdk-6u19-linux-i586-rpm.bin
我们默认将jdk安装于“/usr/java/jdk1.6.0_19”目录吧。
接下来我们需要修改系统环境变量,在terminal窗口中键入“vi /etc/profile”
在这个profile文件内加入两行:
export JAVA_HOME=/usr/java/jdk1.6.0_19
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
打开一个terminal窗口并输入
看到正确的jdk版本信息后即代表我们的jdk在linux下安装正确了
还是编辑那个profile文件并加入如下几行:
export JAVA_HOME=/usr/java/jdk1.6.0_19
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=$ORACLE_BASE/product/10
export ORACLE_SID=ktdb
export ORACLE_TERM=xterm
export NLS_LANG=AMERICAN_AMERICA.UTF8
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib:/lib:/usr/lib:/usr/local/lib
通过上述环境变量我们可以得知,我们的oracle装安装在/opt/oracle/product/10目录下,所以
这些变量是Oracle在安装过程中需要读取的,在windows下安装oracle是不需要设这些东西的。
groupadd oinstall
groupadd dba
useradd -g oinstall -G dba oracle
passwd oracle
mkdir -p /opt/oracle/ product/10
chown -R oracle.oinstall /opt/oracle/
xhost +
DISPLAY=:0.0; export DISPLAY
它代表使得所有的用户可以使用图形化界面来运行相关的图形化应用程序,因为Linux的安全机制相当的严格,root是最高权限,除去root以外的其它用户如果需要拥有root才能执行的权限就需要授予权
一般来讲,Oracle主要需要下面的这些Lib库
gcc-3.2.3-2
make-3.79
binutils-2.11
openmotif-2.2.2-16
setarch-1.3-1
compat-gcc-7.3-2.96.122
compat-gcc-c++-7.3-2.96.122
compat-libstdc++-7.3-2.96.122
compat-libstdc++-devel-7.3-2.96.122
Oracle10g在Linux下有版本检查的限制,如果你的Linux RedHat的版本低于5,那么你可以在Oracle的安装盘disk1下,直接运行如下命令调出图形化安装界面
./runInstaller
/runInstaller –ignoreSysPrereqs
主安装界面出现
按照上述步骤一步步把Oracle装上,注意安装时字符集永远选用AL32UTF-8,这样你的Oracle才能支持多语言。
编辑/etc/rc.local/文件
以下是dbstart.sh文件的内容
存盘后每次你重启Linux,Oracle就会随着你的Linux的开机而自动运行起来了(还有更专业的设置,将在以后的教程中传授,对于初学者想自己搭个环境的选用这个,嘿嘿)。
其们在使用sys用户连上Oracle后可以使用这条命令来显示这三个兄弟
show parameter processes;
session与processes是绑定的,用下面的公式:
sessions=1.1*processes + 5
所以你只有改这个processes,session才会自动调整,我们可以使用下面这条命令去改变系统中的processes
alter system set processes=500 scope = spfile;
这个processes不是乱设的,是要和你系统的内核设置去绑定的。
我们的Oracle性能调优主要用围绕上述几个章节来做介绍,我们不介绍太高深的莫明奇妙的理论,在这边我们对这几个方面做一个统用的解释和实际应用场景,如果是新手,你在看过这篇教程后应该知道一个oracle的性能主要从几个方面(Common)去着手,对一个熟手来说上述每个小节的具体内容都是可以在Oracle的DBA手册中找到更详细的内容。
Oracle的连接服务是基于主机名的,我们需要设置装Oracle这台主机的唯一主机名,这样客户端才能通过TNS来连上Oracle的服务
请更改Oracle所在服务器上的 /etc/hosts文件
# Do not remove the following line, or various programs
# that require network functionality will fail.
192.168.1.3 myoracleserver
127.0.0.1 localhost.localdomain localhost
编辑注册表
把这个NLS_LANG改成上图中所示,这样你的Oracle的客户端上可以直接通过客户端工具或者是第三方客户端工具进行中文的正常录入了而不是乱码了。
使用system帐号登录
一般我们创建一个表空间和一个临时表空间
然后我们就可以开始创建用户了
对于一个j2ee的应用连接Oracle来说,这个连接用户的角色只需要具有上述两个权限就够用了,有些人喜欢给这个用户DBA权限是太绝对了,当然这样给角色使用起来方便,什么权限都有了,不需要我在开发时再进行细化的设置了。
可是,你有没有想到过,一旦你的应用被人sql injection后,而你的应用上连接着oracle的用户是dba权限,那么你连整个数据库是不是都会被泄密啊?
一个Oracle内的用户默认可以让你重复登录10次,10次的限制一到,这个用户就会被锁住。
可以用下列语句查看一个Oracle用户重复几次后会被锁住的设置参数
SELECT * FROM dba_profiles s WHERE s.profile='DEFAULT' AND resource_name='FAILED_LOGIN_ATTEMPTS';
当然这样做是为了安全考虑。
可是,在我们的开发环境中,有时往往因为一个循环,一个登录器,一个线程写错而导致Oracle连接用户重复需要连接Oracle 数次,因此经常开发人员会向DBA抱怨说 “我的用户又被锁住了”。
因此,在开发环境我建议你把这个“重复连接次数”去掉,设成下面这样
ALTER PROFILE DEFAULT LIMIT FAILED_LOGIN_ATTEMPTS UNLIMITED
关于SGA这块的调整,网上有太多优秀的文章。
一般可以通过修改$ORACLE_HOME/dbs目录下的init.ora文件来自行调整,但是。。。。。。
如果你要调整一个init.ora文件,请使用下面的步骤可确保你的修改不会造成Oracle启动不了
在Linux下使用下面这条命令
strings spfilektdb.ora > init.ora.bak
一个init*.ora对应一个spfile*.ora
sqlplus sys/password@databaseSID as sysdba
登录成功后运行下面两条命令
shutdown immediate
startup pfile='/opt/oracle/product/10/dbs/init.ora.bak‘
create spfile from pfile='/opt/oracle/product/10/dbs/init.ora.bak';
startup force
Oracle的表空间文件都放在$ORACLE_HOME/oradata如/opt/oracle/product/10/oradata这样的目录中的
即在Oracle运行时发觉表空间不够时可以直接打开Oracle的管理界面来动态给它划一块硬盘空间,或者甚至你又装了一块硬盘进服务后,Oracle可以把表空间在运行时扩展到新插入的磁盘中。
ORACLE的表空间划分将影响ORACLE的数据访问速度。
对于表空间来说,最重要的是如何把要连续访问的段放在一起,但是由于oracle 不能提供基于段的统计信息,所以对数据的物理模型设计和访问模式的详细了解对表空间的规划有非常大的好处。然后基于这些原则,我们就可以制定我们的表空间划分原则了:
段大小 | 区片大小 |
128M | 128K |
128M-4G | 4M |
4G及以上 | 128M |
当传统的导入导出遇到了海量数据时~
我在以前一个工程碰到过一个真实的案例,48-50张左右的表,每张表最大数据量为1200万,最小的在280-300万左右的数据,占用硬盘空间在14-16GB左右的一个.dmp包。不定期会进行导入导出操作。
于是我们的数据库负责人员就使用传统的imp/exp命令了。
每一次imp都需要耗费达4-6个小时,有时一旦出错。。。完蛋了,这个效率太低,大家不要看1200万这个数量,大家会说:哟,都是几百万的数据,可是这点数据其实还不算是真正的大数据量,imp一次要4-6小时,这是绝对不合理的。
传统的imp命令在导入时,如果只是仅处理数据,千万条数据对Oracle的处理来说根本就是”毛毛雨“啦,关键是在它导入了数据后,而要对每个表重新做一次索引。
一边导一边索引,一边一条条commit,就好比你用一个循环来insert 1万条数据和你改用statemenet.addBatch(query);的效率的对比一样,一定是后者更快更高效。
因此,在碰到这种情况下我们建议对imp导入命令做下面的折分:
这样,我们原来的imp命令就变成下面这样的样子了:
imp user2/pwd fromuser=user1 touser=user2 file=file commit=y feedback=10000 buffer=10240000 ignore=y rows=y indexes=n
imp user2/pwd fromuser=user1 touser=user2 file=file commit=y feedback=10000 buffer=10240000 ignore=y rows=n indexes=y
这两条命令是先后发起的,在只导数据时对于上述的14gb左右的一个.dmp包在同样软硬件环境中只用了15-20分钟,后一条建索引语句只用了25-27分钟。
这其中,提高了几倍?大家想想。
编辑这个 /etc/security/limits.conf
* soft nofile 1024
* hard nofile 1024
它代表Linux系统下最大打开文件数,如java里面的jdbc connection操作,new File操作都是一个文件打开操作,1024这个值是很少的。
所以我们把它改成
* soft nofile 300000
* hard nofile 300000
oracle soft memlock 1048576
oracle hard memlock 1048576
memlock’s value=Oracle share_pool_size (gb)*1024*1024
所以你的Oracle中的SGA里的share_pool_size的大小是受到这个值的限制的。
改完后重启Linux系统,然后我们可以使用下面的命令来看我们修改的效果。
ulimit –a
使用Oracle用户登录
su – oracle
然后键入
ulimit -l
就可以看到oracle soft memlock的相关修改效果了。
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
#SEMMSL SEMMNS SEMOPM SEMMNI
其中最后一行带”#“是我加的,代表这几个数值的”含义“,那么光有含义,没有解释?下面给出解释
SEMMSL=max processes+10
SEMMNS=SEMMSL*SEMMNI
看到没有。。。。。。所以说Oracle中这个processes不是乱设的,是要和你系统的内核设置去绑定的。
我去年写过篇博文,那篇博文是用于记录如何在实际的一个项目中在32位Linux操作系统下让Oracle的SGA突破2GB内存这个限制,详细可见:oracle在32位的Linux环境下SGA如何突破2GB内存限制的最终解决方案
在这边,我再做一下补充。
一些客户,这主要是客户关系,如果换成我我一定要买支持64位操作系统的服务器。
一些使用32位操作系统的客户安装Oracle,大家知道Oracle自从8.0后开始全面转成Java,因此它也受到JAVA虚拟机在32位操作系统下最多只能使用到2GB物理内存这个限制。
因此,当你的机器物理内存有32GB时,但因为你用了32位的操作系统,因此你的Oracle在创建Database时即customer(定义)这个数据库内存分匹时你的SGA是超不过2048MB的。
SGA中有一个很重要的指标即:shared_pool_size,这个值的大小会直接影响性能,关于shared_pool_size有很多更深入的理论性的探讨,这边告诉初学者或者新手,这个值相当于”游戏推荐配置“,不满足,游戏运行暴卡,超过这个值,游戏运行流畅。
但是,我现在有台服务器,物理内存32GB,用的是32位的Linux,我Oracle的SGA想要突破这个2GB大小的限制,又不能重装(客户环境不是你说要重装就要重装的)怎么办?只有想办法:
{DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */
or
{DELETE|INSERT|SELECT|UPDATE} --+ hint [text] [hint[text]]...
/*+ALL_ROWS*/
/*+FIRST_ROWS*/
/*+CHOOSE*/
/*+RULE*/
/*+FULL(TABLE)*/
/*+ROWID(TABLE)*/
/*+USE_HASH(BSEMPMS,BSDPTMS)*/
ANALYZE TABLE ktdb.T_CD_CODE COMPUTE STATISTICS;
ANALYZE TABLE ktdb.T_CD_CODE COMPUTE STATISTICS for all indexed columns;
spool 'd:\analyzetable.txt‘
select * from user_tables;
spool off
spool 'd:\analyzeindex.txt‘
select * from user_indexes ;
spool off
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=$ORACLE_BASE/product/10
export ORACLE_SID=ktdb
$ORACLE_HOME/bin/sqlplus "sys/sys@ktdb as sysdba" <
PARTITION BY RANGE (CUSTOMER_ID)
(
PARTITION CUS_PART1 VALUES LESS THAN (100000) TABLESPACE
CUS_TS01, PARTITION CUS_PART2 VALUES LESS THAN (200000)
TABLESPACE CUS_TS02
)
CREATE TABLE emp
(
empno NUMBER (4),ename VARCHAR2 (30),sal NUMBER
)PARTITION BY HASH (empno) PARTITIONS 8
STORE IN (emp1,emp2,emp3,emp4,emp5,emp6,emp7,emp8);
create table dinya_test
(
transaction_id number primary key,item_id number(8) not null,transaction_date date
) partition by range(transaction_date)subpartition by hash(transaction_id) subpartitions
3 store in (dinya_space01,dinya_space02,dinya_space03)
(
partition part_01 values less than(to_date(‘2006-01-01’,’yyyy-mm-dd’)),
partition part_02 values less than(to_date(‘2010-01-01’,’yyyy-mm-dd’)),
partition part_03 values less than(maxvalue)
);
EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('schema名', '你将要被切换的表名', DBMS_REDEFINITION.CONS_USE_PK);
EXEC DBMS_REDEFINITION.START_REDEF_TABLE('schema名','你将要被切换的表名', '拥分区结构的新表');
EXEC DBMS_REDEFINITION.sync_interim_table('schema名', '你将要被切换的表名', '拥分区结构的新表');
EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('schema名', '你将要被切换的表名', '拥分区结构的新表');
exec DBMS_REDEFINITION.ABORT_REDEF_TABLE('schema名','你将要被切换的表名','拥分区结构的新表');