话说 Oracle ACE 这回事儿

2010-08-24

有1人发表了评论 | 赶紧发表评论吧 | 作者:sky

前段时间,在有幸被多人举荐并由 Oracle 公司的 Jack 提名后,被 Oracle 公司授予了 Oracle ACE (Expertise: MySQL) 称号。

很多朋友听闻此事后都向我道贺,也有很多朋友提出疑问: Oracle ACE 到底为何物?

Oracle ACE 程序主要是 Oracle 公司为了奖励使用推广Oracle公司某个领域产品的技术专家们所做的贡献而设立的一种荣誉机制。目前,除了通过业内知名人士举荐并由 Oracle 公司的人提名最终经过 ACE 程序审核小组评审之外,无法通过认证考试或者是其他途径获得。

目前国内共有 16 位技术专家获此荣誉,分别分布在6个技术领域,如下:

  • Database Management & Performance:5人
  • Database App Development:5人
  • Middleware & SOA:4人
  • Applications & Apps Technology:1人
  • MySQL:1人

其中 MySQL 领域目前国内就我一个人(希望在未来能够有越来越多的战友们能够加入这个行列),全球也只有4位。能够获此殊荣,确实非常开心,这是对我个人在这个技术领 域内的认可。当然,这也离不开我所在的公司为我提供的成长平台,离不开所在Team的各位同事给我的帮助。同时,也希望国内有更多的技术专家能够获得 ACE 称号。

原文出自: Sky.Jian – i Sky000

话说 Oracle ACE 这回事儿



核心业务系统数据库平台迁移: Oracle -> MySQL

2010-08-24

有4人发表了评论 | 赶紧发表评论吧 | 作者:sky

为了对核心技术拥有更多的自主控制能力,为了解决数据库的线性扩展问题,为了尽量减少对商业软件的依赖,为了摆脱对高端硬件的依赖,为了… 基于以上多种原因,2年前,我们计划将公司某核心应用平台进行大手术:数据库平台从软件到硬件全部重构。当然,这其中应用架构的改造也不可避免的进行了大 换血。

这个项目无论是从技术角度还是是业务角度来说,都对我们有着非常大的价值,也必定会带来非常深远的影响。项目历时2年多,分4个阶段才完成:

  • 应用接口统一
  • 这一阶段主要是为了后面真正迁移的时候做准备工作,将该核心应用系统的所有数据访问入口统一到一起,全部以服务化的接口方式呈现给其他有需要的系统,一来方便后续变更的控制,二来也推进了服务化的进程。

  • Oracle数据库中拆分(1拆16)
  • 这个阶段本不是必要的,但是由于项目启动稍微晚了点,数据出现了爆发性增长,导致该系统的数据表太大(单表不带索引过500GB),原 Oracle 数据库已经快撑不住了。为了安全起见,先在 Oracle 中从一个主表以会员ID进行 hash 运算后再进行水平拆分,从1个表分拆成了16个。附表由于访问量稍小,而且全部是根据主键访问,暂时保留原样。

    当然,这样的水平拆分,必然会带来数据访问路由以及数据合并的问题。我们专门为此开发了具有分布式数据库路由/数据合并,数据库读写分离,数据库链接管理等功能的数据访问中间层,专门解决拆分后给应用服务器带来的影响,使得应用服务器完全感受不到后端数据库的变化。

    这个数据访问中间层,对前端应用服务器来说,就是一个完整的数据库,所有数据请求都从这里实现,以协议的方式和前端应用服务器的jdbc驱动进行交互,以便让数据库对应用服务器彻底透明。

  • Oracle迁移至 MySQL(16拆128)
  • 这个阶段是整个阶段中历时最长,复杂度最高,风险系数最高的,未知因素也最多的一个阶段。虽然 MySQL 数据库已经在互联网行业占据了大片江山,但是对于阿里巴巴来说,却仍然是一个新鲜玩意儿,因为之前我们一直都用 Oracle 来提供所有的业务系统的数据库服务。

    在此之前,我们从来没有在如此核心业务系统的数据库上使用过 PC Server 和本地硬盘来承载数据库,一直是使用 IBM 小型机和中高端存储设备来解决高性能和高可靠的问题。在更换成 PC Server 和本地硬盘来承载数据库之后,我们就必须面对 PC Server 本身硬件可能存在的不可靠性所带来的 Crash,所以我们必须有一套完善的 HA 切换机制,要比小型机厂商所提供的商业 HA 管理软件更加高效更加自动化更加可控,才能我们降低了设备本身可靠性之后达到原有的可用性要求。

    对于一个需要满足 365 * 24 * 7 的核心业务系统来说,肯定是不可能给我们太多时间来进行数据迁移的,所以我们不得不设计出一个对现有系统影响尽可能小的迁移方案,这势必会造成方案的高度复杂化,带来更多的风险。最后的迁移方案要经历如下4个阶段:

    1. Oracle 读/写;;MySQL 初始化并增量写
    2. Oracle 读/写; MySQL 写
    3. Oracle 写; MySQL 读/写
    4. Oracle 停访问; MySQL 读/写

    当然,也正式由于有如此复杂的方案,才确保了在整个迁移过程中的的停机时间被控制在了10分钟之类。

  • 附属Detail信息迁移至 MySQL
  • 从项目开始,至完成主表拆分结束,已经接近2年了。这2年时间内,数据量一直都在飞涨,这让即使仅仅只是按照主键访问的附表也快无法承受持续增长的 业务压力,附表的拆分也就成了必行之势。由于在原来主表拆分的过程中,整个项目组已经积累了大量的经验,附表拆分过程非常顺利,基本没有出现任何问题。虽 然附表的拆分过程与主表相比除了 1拆16这个阶段外没有减少其他任何环节,但是整个拆分过程也才2个月就全部搞定了。

这个迁移项目算是彻底完成了,但是我们的迁移之路并不会就此止步,还有很多的系统仍然存在扩展性问题,还有很多的数据库应用等着我们去拆分。

注:同事们还为此送了我们一个虽不太雅但也意思相近的名称 “拆迁队”。

原文出自: Sky.Jian – i Sky000

核心业务系统数据库平台迁移: Oracle -> MySQL



Alibaba DBA Team 2010/08

2010-08-10

有9人发表了评论 | 赶紧发表评论吧 | 作者:grassbell

Alibaba DBA 2010/8



MySQL Query Cache 小结

2010-07-05

有3人发表了评论 | 赶紧发表评论吧 | 作者:sky

最近经常有人问我 MySQL Query Cache 相关的问题,就整理一点 MySQL Query Cache 的内容,以供参考。

顾名思义,MySQL Query Cache 就是用来缓存和 Query 相关的数据的。具体来说,Query Cache 缓存了我们客户端提交给 MySQL 的 SELECT 语句以及该语句的结果集。大概来讲,就是将 SELECT 语句和语句的结果做了一个 HASH 映射关系然后保存在一定的内存区域中。

在大部分的 MySQL 分发版本中,Query Cache 功能默认都是打开的,我们可以通过调整 MySQL Server 的参数选项打开该功能。主要由以下5个参数构成:

  • query_cache_limit:允许 Cache 的单条 Query 结果集的最大容量,默认是1MB,超过此参数设置的 Query 结果集将不会被 Cache
  • query_cache_min_res_unit:设置 Query Cache 中每次分配内存的最小空间大小,也就是每个 Query 的 Cache 最小占用的内存空间大小
  • query_cache_size:设置 Query Cache 所使用的内存大小,默认值为0,大小必须是1024的整数倍,如果不是整数倍,MySQL 会自动调整降低最小量以达到1024的倍数
  • query_cache_type:控制 Query Cache 功能的开关,可以设置为0(OFF),1(ON)和2(DEMAND)三种,意义分别如下:
    • 0(OFF):关闭 Query Cache 功能,任何情况下都不会使用 Query Cache
    • 1(ON):开启 Query Cache 功能,但是当 SELECT 语句中使用的 SQL_NO_CACHE 提示后,将不使用Query Cache
    • 2(DEMAND):开启 Query Cache 功能,但是只有当 SELECT 语句中使用了 SQL_CACHE 提示后,才使用 Query Cache
  • query_cache_wlock_invalidate:控制当有写锁定发生在表上的时刻是否先失效该表相关的 Query Cache,如果设置为 1(TRUE),则在写锁定的同时将失效该表相关的所有 Query Cache,如果设置为0(FALSE)则在锁定时刻仍然允许读取该表相关的 Query Cache。

Query Cache 如何处理子查询的?
这是我遇到的最为常见的一个问题。其实 Query Cache 是以客户端请求提交的 Query 为对象来处理的,只要客户端请求的是一个 Query,无论这个 Query 是一个简单的单表查询还是多表 Join,亦或者是带有子查询的复杂 SQL,都被当作成一个 Query,不会被分拆成多个 Query 来进行 Cache。所以,存在子查询的复杂 Query 也只会产生一个Cache对象,子查询不会产生单独的Cache内容。UNION[ALL] 类型的语句也同样如此。

Query Cache 是以 block 的方式存储的数据块吗?
不是,Query Cache 中缓存的内容仅仅只包含该 Query 所需要的结果数据,是结果集。当然,并不仅仅只是结果数据,还包含与该结果相关的其他信息,比如产生该 Cache 的客户端连接的字符集,数据的字符集,客户端连接的 Default Database等。

Query Cache 为什么效率会非常高,即使所有数据都可以 Cache 进内存的情况下,有些时候也不如使用 Query Cache 的效率高?
Query Cache 的查找,是在 MySQL 接受到客户端请求后在对 Query 进行权限验证之后,SQL 解析之前。也就是说,当 MySQL 接受到客户端的SQL后,仅仅只需要对其进行相应的权限验证后就会通过 Query Cache 来查找结果,甚至都不需要经过 Optimizer 模块进行执行计划的分析优化,更不许要发生任何存储引擎的交互,减少了大量的磁盘 IO 和 CPU 运算,所以效率非常高。

客户端提交的 SQL 语句大小写对 Query Cache 有影响吗?
有,由于 Query Cache 在内存中是以 HASH 结构来进行映射,HASH 算法基础就是组成 SQL 语句的字符,所以必须要整个 SQL 语句在字符级别完全一致,才能在 Query Cache 中命中,即使多一个空格也不行。

一个 SQL 语句在 Query Cache 中的内容,在什么情况下会失效?
为了保证 Query Cache 中的内容与是实际数据绝对一致,当表中的数据有任何变化,包括新增,修改,删除等,都会使所有引用到该表的 SQL 的 Query Cache 失效。

为什么我的系统在开启了 Query Cache 之后整体性能反而下降了?
当开启了 Query Cache 之后,尤其是当我们的 query_cache_type 参数设置为 1 以后,MySQL 会对每个 SELECT 语句都进行 Query Cache 查找,查找操作虽然比较简单,但仍然也是要消耗一些 CPU 运算资源的。而由于 Query Cache 的失效机制的特性,可能由于表上的数据变化比较频繁,大量的 Query Cache 频繁的被失效,所以 Query Cache 的命中率就可能比较低下。所以有些场景下,Query Cache 不仅不能提高效率,反而可能造成负面影响。

如何确认一个系统的 Query Cache 的运行是否健康,命中率如何,设置量是否足够?
MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态,具体如下:

  • Qcache_free_blocks:目前还处于空闲状态的 Query Cache 中内存 Block 数目
  • Qcache_free_memory:目前还处于空闲状态的 Query Cache 内存总量
  • Qcache_hits:Query Cache 命中次数
  • Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,也就是没有命中的次数
  • Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数
  • Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL
  • Qcache_queries_in_cache:目前在 Query Cache 中的 SQL 数量
  • Qcache_total_blocks:Query Cache 中总的 Block 数量

可以根据这几个状态计算出 Cache 命中率,计算出 Query Cache 大小设置是否足够,总的来说,我个人不建议将 Query Cache 的大小设置超过256MB,这也是业界比较常用的做法。

MySQL Cluster 是否可以使用 Query Cache?

其实在我们的生产环境中也没有使用 MySQL Cluster,所以我也没有在 MySQL Cluster 环境中使用 Query Cache 的实际经验,只是 MySQL 文档中说明确实可以在 MySQL Cluster 中使用 Query Cache。从 MySQL Cluster 的原理来分析,也觉得应该可以使用,毕竟 SQL 节点和数据节点比较独立,各司其职,只是 Cache 的失效机制会要稍微复杂一点。

原文出自:MySQL Query Cache 小结



ORACLE BITMAP INDEX

2010-05-24

有6人发表了评论 | 赶紧发表评论吧 | 作者:vogts

ORACLE的bitmap索引,我们用的很少。在我们的常理认识当中,我们用的最多就是类似性别,类型这种属性的字段,因为他们字段的种类很少。其实 BITMAP还是有很多优势以及一些特性的。

首先在传统的INDEX里,我们在索引的存储上,一般是分为:header+index length+index value+rowid组成。如图:

2010-05-24_142946

bitmap的存储结果相对来说,复杂一点。 bitmap 不存储rowid。那么rowid存储在哪里呢?答:每一个bitmap的头部,都存储了rowid的启示位置与结束位置。ORACLE通过自己的内部算 法,算出来相应的ROWID。
位图中的每一位,都记录是否有值。
如表的记录是这样存储的:

row-value
male
female
female
male

那么对应的bitmap则是这样存储的:

rowid的启示位置与结束位置 rowid的启示位置与结束位置
male female
1 0
0 1
0 1
1 0

由 此可见,存储的空间大大的节省了,另外带来的收益就是扫描的BLOCK也大大减少了。

如果查找性别是male的数据,ORACLE只会去 搜索MALE这一列,然后是1的记录,返回即可。

如果是针对BITMAP字段本身做OR,AND这样的查询,那么ORACLE会在 BITMAP索引内部,先做一次判断,找出符合结果的,再去计算ROWID,最后给出相应的VALUE,示意图如下:

dwhsg093

bitmap join index
bitmap join index,它的特点就是将多张表的JOIN结果,存储在一个索引里面,然后使用BITMAP的形式进行存储。图难画了,请见谅,改天有空的时候,再把图 补上。这个对于类似DW那样的多表join效率提高很明显。
我今天做了一个测试,是用3张表join来做的,原来的SQL是这样的:
test@DB>                       select wt_cust.company_name,wt_cust.gmt_create
2   from wt_cust,wt_CUST_EXT ,wt_CUST_BOOK
3  where wt_cust.id=wt_CUST_EXT.Cust_Id
4  and wt_CUST_BOOK.Cust_Id=wt_cust.id;

58 rows selected.

Elapsed: 00:00:00.01

Execution Plan
———————————————————-

—————————————————————————————————-
| Id  | Operation                     | Name                          | Rows  | Bytes | Cost (%CPU)|
—————————————————————————————————-
|   0 | SELECT STATEMENT              |                               |    54 |  2484 |   179   (0)|
|   1 |  NESTED LOOPS                 |                               |    54 |  2484 |   179   (0)|
|   2 |   NESTED LOOPS                |                               |   177 |  7257 |   179   (0)|
|   3 |    INDEX FULL SCAN            | wt_CUST_BOOK_UK     |   177 |  1062 |     1   (0)|
|   4 |    TABLE ACCESS BY INDEX ROWID| wt_CUST             |     1 |    35 |     2   (0)|
|*  5 |     INDEX UNIQUE SCAN         | wt_CUST_PK          |     1 |       |     1   (0)|
|*  6 |   INDEX RANGE SCAN            | wt_CUST_EXT_CID_IND |     1 |     5 |     0   (0)|

—————————————————————————————————-

一 个3表join,效率很差。如果我们创建BITMAP JOIN INDEX则可以避免这种情况的发生:
test@DB>CREATE BITMAP INDEX cust_wt_test
2  ON     wt_cust(wt_cust.company_name)
3  FROM   wt_cust,wt_CUST_EXT ,wt_CUST_BOOK
4  WHERE  wt_cust.id=wt_CUST_EXT.Cust_Id
5  and wt_CUST_BOOK.Cust_Id=wt_cust.id
6  tablespace test_ind  ;

Index created.

Elapsed: 00:00:00.08
再来看看SQL的执行计划:
xx@DB>select  wt_cust.company_name,wt_cust.gmt_create
2   from wt_cust,wt_CUST_EXT ,wt_CUST_BOOK
3  where wt_cust.id=wt_CUST_EXT.Cust_Id
4  and wt_CUST_BOOK.Cust_Id=wt_cust.id;

58 rows selected.

Elapsed: 00:00:00.00

Execution Plan
———————————————————-

—————————————————————————————
| Id  | Operation                    | Name              | Rows  | Bytes | Cost (%CPU)|
—————————————————————————————
|   0 | SELECT STATEMENT             |                   |  1834K|    61M|   219K  (1)|
|   1 |  TABLE ACCESS BY INDEX ROWID | wt_CUST |  1834K|    61M|   219K  (1)|
|   2 |   BITMAP CONVERSION TO ROWIDS|                   |       |       |            |
|   3 |    BITMAP INDEX FULL SCAN    | CUST_WT_TEST      |       |       |            |
—————————————————————————————

请 着重注意红色部分。逻辑读大大降低!!
BTW:
我觉得我们除了传统的NESTLOOP,MERGE JOIN,HASH JOIN。这样看来又多了一种优化JOIN的方式。

总结:
bitmap我们可能平时使用的不多,但是觉得它在特殊的应用场景,还 是有优势的。bitmap join index更是一种多表JOIN的新方式,很有意思。



在Vmware上安装Oracle 11gR2 的安装简易手册

2010-05-20

有3人发表了评论 | 赶紧发表评论吧 | 作者:jametong

有感于今天内部被问到的一个问题

1. 运行如下的rpm命令,找到安装Oracle需要而没有安装的rpm包.并mount Redat安装盘安装这些包.

rpm -qv binutils-2.17.50.0.6 \
compat-libstdc++-33-3.2.3 \
elfutils-libelf-0.125 \
elfutils-libelf-devel-0.125 \
elfutils-libelf-devel-static-0.125 \
gcc-4.1.2 \
gcc-c++-4.1.2 \
glibc-2.5-24 \
glibc-common-2.5 \
glibc-devel-2.5 \
glibc-headers-2.5 \
kernel-headers-2.6.18  \
ksh-20060214 \
libaio-0.3.106 \
libgcc-4.1.2 \
libgomp-4.1.2 \
libstdc++-4.1.2  \
libstdc++-devel-4.1.2 \
make-3.81 \
sysstat-7.0.2 \
libaio-devel-0.3.106  \
unixODBC-2.2.11  \
unixODBC-devel-2.2.11
mkdir /media/cdrom/
mount -t iso9660 /dev/cdrom /media/cdrom/
cd /media/cdrom/Server/
rpm -ivh sysstat-7.0.2-1.el5.i386.rpm libaio-devel-0.3.106-3.2.i386.rpm unixODBC-2.2.11-7.1.i386.rpm unixODBC-devel-2.2.11-7.1.i386.rpm

2. 关闭大部分无用的服务(可能因人因环境而异,这只是我的个人喜好).

chkconfig NetworkManager --level 2345 off
chkconfig NetworkManagerDispatcher --level 2345 off
chkconfig acpid --level 2345 off
chkconfig apmd --level 2345 off
chkconfig auditd --level 2345 off
chkconfig avahi-dnsconfd --level 2345 off
chkconfig bluetooth --level 2345 off
chkconfig capi --level 2345 off
chkconfig conman --level 2345 off
chkconfig cpuspeed --level 2345 off
chkconfig cups --level 2345 off
chkconfig dhcdbd --level 2345 off
chkconfig dund --level 2345 off
chkconfig firstboot --level 2345 off
chkconfig haldaemon --level 2345 off
chkconfig hidd --level 2345 off
chkconfig ip6tables --level 2345 off
chkconfig ipmi --level 2345 off
chkconfig iptables --level 2345 off
chkconfig irda --level 2345 off
chkconfig isdn --level 2345 off
chkconfig kdump --level 2345 off
chkconfig kudzu --level 2345 off
chkconfig lvm2-monitor --level 2345 off
chkconfig mcstrans --level 2345 off
chkconfig mdmonitor --level 2345 off
chkconfig mdmpd --level 2345 off
chkconfig messagebus --level 2345 off
chkconfig microcode_ctl --level 2345 off
chkconfig multipathd --level 2345 off
chkconfig netconsole --level 2345 off
chkconfig netfs --level 2345 off
chkconfig netplugd --level 2345 off
chkconfig nfs --level 2345 off
chkconfig nfslock --level 2345 off
chkconfig nscd --level 2345 off
chkconfig ntpd --level 2345 off
chkconfig pand --level 2345 off
chkconfig pcscd --level 2345 off
chkconfig portmap --level 2345 off
chkconfig psacct --level 2345 off
chkconfig rdisc --level 2345 off
chkconfig readahead_later --level 2345 off
chkconfig restorecond --level 2345 off
chkconfig rhnsd --level 2345 off
chkconfig rpcgssd --level 2345 off
chkconfig rpcidmapd --level 2345 off
chkconfig rpcsvcgssd --level 2345 off
chkconfig saslauthd --level 2345 off
chkconfig sendmail --level 2345 off
chkconfig setroubleshoot --level 2345 off
chkconfig smartd --level 2345 off
chkconfig vncserver --level 2345 off
chkconfig vsftpd --level 2345 off
chkconfig wdaemon --level 2345 off
chkconfig winbind --level 2345 off
chkconfig wpa_supplicant --level 2345 off
chkconfig ypbind --level 2345 off

3. 修改系统参数(这只是我的测试环境,具体环境需要做适应性的调整,而且我这个虚拟机,毋需考虑BigPage,生产环境可能需要考虑,特别是64位环境下的11g环境).

--修改/etc/sysctl.conf
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 536870912
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048586

--修改完毕后, 运行sysctl -p使其生效.

4. 添加用户/组信息.

groupadd -g 501 oinstall
groupadd -g 502 dba
groupadd -g 503 oper
groupadd -g 504 asmadmin
groupadd -g 505 asmdba
groupadd -g 506 asmoper

useradd -g oinstall -G dba,oper,asmdba oracle
useradd -g oinstall -G asmadmin,asmdba,asmoper grid

5. 修改安全配置信息,

  • 1) . Add the following lines to the /etc/security/limits.conf file: (the following example shows the software account owner oracle):
  • 
    oracle              soft    nproc   2047
    oracle              hard    nproc   16384
    oracle              soft    nofile  1024
    oracle              hard    nofile  65536
    
    grid              soft    nproc   2047
    grid              hard    nproc   16384
    grid              soft    nofile  1024
    grid              hard    nofile  65536
    
  • 2). Add or edit the following line in the /etc/pam.d/login file, if it does not already exist:
  • session    required     pam_limits.so
    

    6. 修改/etc/profile 信息,修改Oracle/grid用户登陆后的系统权限.
    For the Bourne, Bash, or Korn shell, add the following lines to the /etc/profile file (or the file
    on
    SUSE Linux Enterprise Server systems /etc/profile.local):

    
    if [ $USER = "oracle" ]; then
      if [ $SHELL = "/bin/ksh" ]; then
        ulimit -p 16384
        ulimit -n 65536
      else
        ulimit -u 16384 -n 65536
      fi
      umask 022
    fi
    
    if [ $USER = "grid" ]; then
      if [ $SHELL = "/bin/ksh" ]; then
        ulimit -p 16384
        ulimit -n 65536
      else
        ulimit -u 16384 -n 65536
      fi
      umask 022
    fi
    

    7. 创建基本的安装目录.并赋予其权限.

    mkdir -p /opt/app/
    mkdir -p /opt/app/oracle/products/11.2.0/
    chown -R oracle:oinstall /opt/app/oracle
    
    mkdir -p /opt/app/grid/products/11.2.0/
    chown -R grid:oinstall /opt/app/grid
    
    chown grid:oinstall /opt/
    chown grid:oinstall /opt/app/
    chown grid:oinstall /opt/app/oracle/
    

    8. 修改用户profile信息.

  • 1). 修改grid用户的profile文件/home/grid/.bash_profile
  • export ORACLE_BASE=/opt/app/oracle
    export ORACLE_HOME=/opt/app/grid/products/11.2.0
    export ORACLE_SID=+ASM1
    CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib:$ORACLE_HOME/network/jlib
    export ORACLE_BASE ORACLE_HOME ORACLE_SID ORA_NLS33 PATH  CLASSPATH TNS_ADMIN
    
    PATH=$ORACLE_HOME/bin:/usr/bin:/etc:/usr/bin/X11:/usr/ccs/bin:/usr/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:/usr/java14/jre/bin:/usr/java14/bin:/usr/local/bin:.:$PATH
    export  PATH
    export PATH=$PATH:$ORACLE_HOME/OPatch
    
    # ORACLE_TERM=xterm; export ORACLE_TERM
    NLS_LANG=AMERICAN_AMERICA.US7ASCII; export NLS_LANG
    
    LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib:/usr/openwin/lib
    LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/td/lib:/usr/ucblib:/usr/local/lib
    export LD_LIBRARY_PATH
    export NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS"
    export UDUMP=/opt/oracle/admin/forum/udump
    export BDUMP=/opt/oracle/admin/forum/bdump
    export SQLPATH=$ORACLE_HOME/sqlplus/admin:~/admin/sql/:~/admin/mysql
    alias sql='sqlplus /nolog'
    alias lm='ls -al'
    export DISPLAY=192.168.68.1:0.0
    
  • 2). 修改Oracle用户profile信息.
  • 
    export ORACLE_BASE=/opt/app/oracle
    export ORACLE_HOME=/opt/app/grid/products/11.2.0
    export ORACLE_SID=rac1
    CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib:$ORACLE_HOME/network/jlib
    export ORACLE_BASE ORACLE_HOME ORACLE_SID ORA_NLS33 PATH  CLASSPATH TNS_ADMIN
    
    PATH=$ORACLE_HOME/bin:/usr/bin:/etc:/usr/bin/X11:/usr/ccs/bin:/usr/bin:/etc:/usr/sbin:/usr/ucb:/usr/bin/X11:/sbin:/usr/java14/jre/bin:/usr/java14/bin:/usr/local/bin:.:$PATH
    export  PATH
    export PATH=$PATH:$ORACLE_HOME/OPatch
    
    # ORACLE_TERM=xterm; export ORACLE_TERM
    NLS_LANG=AMERICAN_AMERICA.US7ASCII; export NLS_LANG
    
    LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib:/usr/openwin/lib
    LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/td/lib:/usr/ucblib:/usr/local/lib
    export LD_LIBRARY_PATH
    export NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS"
    export UDUMP=/opt/oracle/admin/forum/udump
    export BDUMP=/opt/oracle/admin/forum/bdump
    export SQLPATH=$ORACLE_HOME/sqlplus/admin:~/admin/sql/:~/admin/mysql
    alias sql='sqlplus /nolog'
    alias lm='ls -al'
    

    9. 修改/etc/hosts信息,配置RAC信息.

    
    192.168.68.128    rac1-priv.localdomain rac1-priv
    192.168.68.129    rac2-priv.localdomain rac2-priv
    
    192.168.130.128    rac1.localdomain rac1
    192.168.130.129    rac2.localdomain rac2
    
    192.168.130.200   rac-cluster
    192.168.130.210   rac1-vip.localdomain rac1-vip
    192.168.130.220   rac2-vip.localdomain rac2-vip
    

    10. 配置两台主机的ssh 通道.
    分别在root/oracle/grid用户下运行下述命令.

    
    ssh-keygen -b 1024 -t dsa
    

    11. 关闭两个VM节点, 为其添加一块基于Nat的网卡,以及新增两块磁盘(一块作为OCR/Voting Disk用,一块作为SharedStorage使用).
    修改VM文件的配置,新增的磁盘配置为.

    
    disk.locking = "FALSE"
    diskLib.dataCacheMaxSize = "0"
    diskLib.dataCacheMaxReadAheadSize = "0"
    diskLib.dataCacheMinReadAheadSize = "0"
    diskLib.dataCachePageSize = "4096"
    diskLib.maxUnsyncedWrites = "0"
    
    scsi1.present = "TRUE"
    scsi1.virtualDev = "lsilogic"
    scsi1.sharedBus = "VIRTUAL"
    
    scsi1:0.redo = ""
    scsi1:0.present = "TRUE"
    scsi1:0.fileName = "E:\vm\SharedDisk\OCRDisk.vmdk"
    scsi1:0.mode = "independent-persistent"
    scsi1:0.deviceType = "disk"
    
    scsi1:1.redo = ""
    scsi1:1.present = "TRUE"
    scsi1:1.fileName = "E:\vm\SharedDisk\RacShareDisk.vmdk"
    scsi1:1.mode = "independent-persistent"
    scsi1:1.deviceType = "disk"
    

    12. 运行下面的脚本给/dev/sdb;/dev/sdc 进行分区

    
    fdisk /dev/sdc <<_END_
    n
    e
    1
    
    n
    l
    1
    128
    n
    l
    
    256
    n
    l
    
    384
    n
    l
    
    512
    n
    l
    
    640
    n
    l
    
    p
    w
    _END_
    

    13. 在/etc/udev/rules.d/50-udev.rules中添加下面这行配置.

    
    KERNEL=="sd[bc]*",OWNER="grid",GROUP="oinstall",MODE="0660",OPTIONS="last_rule"
    

    并运行/sbin/start_udev使其权限修改生效,否则每次Os重启,文件的权限都会被改成root:disk



    Linux一些页的东西

    2010-05-06

    有8人发表了评论 | 赶紧发表评论吧 | 作者:vogts

    在Linux世界里,分为Page cache,Buffer cache两个层面。其中page cache包含了buffer cache,内存只和page cache交互。

    标准的LINUX总 是假定处理器有三级页表,分别为页目录表(PGD),中间页目录表(PMD)和页表(PTE)。如果程序在进行物理地址转换的时候,中是通过页目录表来索 引中间页目录表,再通过中间页目录表来索引页表,从而查找到某页与内存BLOCK块的对应关系。我把书上的图,拍下来了,哈:

    我们平时只说,page in,page out。file,page cahe,buffer cache,block的关系如下图:

    我们主要讨论下 linux的页的生命:

    在讨论page之前,必须要提及 LINUX的几个关键进程:  kscand, kswapd, kupdated, bdflush. 他们负责LINUX的内存管理。
    一般内存的一页,生命周期如下图:
    free –  在系统启动以后,初始化状态均为FREE。
    active -- 当前被OS使用或者用户进程所使用的状态,均为active。
    inactive dirty(脏数据) -- 当数据被修改过以后,kscand进程会周期性的对内存中的数据进行扫描。如果最近被访问过了,计数器就会加1,否则被减1。如果kscand发现计数器 是0的时候,就会把该页,放到非队列(inactive laundry)里去了。
    inactive laundry(非活动队列) -- 当被放到inactive laundry里的时候,OS才真正的进行I/O操作,写入磁盘。
    inactive clean -- 意味着数据已经被sync到了本地磁盘,该页也已经标示为free。
    另:
    如果想自己强行把脏数据,写到磁盘 上,就使用“sync”命令。
    个人总结:
    今天看了一个晚上这方面的书和文档,感觉LINUX的机制和ORACLE大同小异啊。其实这个世界什么东西,都大同小异啊,关键 是你要想明白,计算机世界永远离不开if,else,for;就如同汽车世界永远离不开发动机,地盘,等等。LINUX本身也有LRU,只是有的地方叫 “Buddy Allocator”。


    Oracle高可用架构

    2010-03-19

    目前还没有人发表评论 | 赶紧发表评论吧 | 作者:jametong

    今天在Uwe Hesse的Blog上看到这篇文章,感觉很不错,简要地描述Oracle MAA架构的所有相关产品,虽然之前就有接触所有这些解决方案,但解释的如此清楚明了的还是第一次看到,特将其翻译如下. 原文: Oracle Database HA Architecture

    Oracle高可用架构
    作者: Uwe Hesse, 译者: Jametong
    Oracle高可用架构是我所讲课程里的一个热门话题.本文尝试对此话题做一个总体的说明,内容涵盖”普通的”单实例数据库,DataGuard,RAC以及扩展RAC(有时也被称为”伸展集群”).Rac与Dataguard组合在一起就是Oracle公司推广的最大可用性架构(Maximum Availability Architecture,MAA).除这些Oracle的HA解决方案外,我还会简单介绍一个第三方的HA解决方案(远程镜像,Remote Mirroring).我不准备深入介绍所有这些解决方案的细节,而只是想做出一点区分的工作,并简要介绍它们各自的优势以及可能的缺陷.
    首先,我们将考察目前为止仍然是应用最为广泛的Oracle数据库架构:单实例数据库.一个Oracle数据库总是由一个数据库(由数据文件,在线重做日志控制文件组成)与一个实例(有内存结构,比如数据库高速缓冲区;以及后台进程,例如数据库写进程)组成.如果我们有一个数据库以及多个访问这个数据库的实例,这就是一个RAC.如果只有一个实例访问这个数据库,就是单实例数据库.下图是一个所有组件都存储在一个服务器上的简单安装版本:

    将数据库文件放置在SAN(存储区域网络)的配置也是目前比较常见的配置,如下图所示:

    从高可用的角度来看,这个架构是非常脆弱的:服务器A与服务器B都是单点故障,数据库A与数据库B也都是单点故障.从而这些服务器所在的站点也是单点故障.这样,只要其中一个单点发生故障,整个数据库将不可用.一个”普通的”RAC就是为了解决其中的服务器单点故障的,如下图所示:

    如果两个服务器的其中一个发生故障,数据库C将仍然可用.当然,使用RAC并不仅仅是为了实现HA.在使用RAC的其它的理由中,一个比较可靠的理由是为了实现伸缩性(Scalability):如果应用需求在将来出现增长,我们可以通过添加新的节点(Node)到集群中来解决.另外,通过使用RAC我们还可以选择使用服务管理(Service-Management)与负载均衡(Load Balance).简言之,RAC不仅仅是HA,在此详述其它原因已经超出本文的范畴了.从HA的视角看,使用RAC的缺陷是:数据库C以及相应的站点C是单点.如果站点C发生故障(比如火灾),数据库C将不可用.因此,将数据库伸展到两个站点就成为我们的选择了,这也是通常所说的扩展RAC.

    现在,这两个站点就不再是单点了.数据库D是在两个站点之间做镜像的.这个架构的缺陷是两个站点之间的网络连接的成本,如果两个站点之间的距离比较远的话.这很关键,因为需要镜像的数据量会非常大.实际上,这使得两个站点之间的距离局限于几公里以内,而这与想要实现的灾难保护目标之间有冲突.这时,Dataguard就隆重登场了:利用DataGuard,我们很容易就可以实现长距离的灾难保护,因为,此时我们不再需要传输所有的数据量,而仅仅需要传输(相对小)的重做日志.在下图中,每个服务器都像上面的服务器A与服务器B一样,只有一个实例:

    备用数据库由来自主数据库的重做日志. 当主库发生故障时,我们可以失败切换(Failover)到备库上并继续有效工作.这个失败切换工作可以由一个Observer(观察员程序,通常称为快速启动失败切换,Fast-Start Failover)自动实现.两个站点之间的距离达到几千公里(依赖于重做日志的传输策略与保护级别(protection level)).如果我们将RAC与Dataguard集合起来,我们就实现了MAA.显然,MAA是一个昂贵的解决方案,不过它也同时享有RAC与Dataguard的所有好处.
    远程镜像是一个广受欢迎的第三方HA解决方案.总体上,它的架构与下图类似:

    这时,也没有哪个站点是单点的,类似于使用扩展RAC架构.这个解决方案的缺陷是:站点间的距离也是严格受限制的,理由与扩展RAC架构类似.同时,在镜像进行的时候,第二个站点是无法提供服务的,这一点与上述的Oracle提供的HA解决方案不同.使用RAC时,所有的服务器与相应的站点都可以提供服务.哪怕是使用Dataguard,备用数据库也不仅仅是等待主库发生故障.除此之外,它还可以提供只读访问服务,这将可以有效降低主库的负载.

    上图展示了Oracle 11g的新特性”物理备用数据库上的实时查询”.在恢复过程中时,备用数据库也在同时提供只读访问.另外,还可以在物理备库(Physical Standby)上做离线备份(OffLoad Backup).

    附注:
    其实还有另外一种可选择的架构. 基于Data Guard与单实例的一个结合.
    类似于上面介绍的远程Data Guard方案, 做了一点修正: 将当前主库的一组Redo 日志放到远程(当然也受限于距离所产生的San 访问延时).



    较旧的文章

    阿里巴巴DBA出品