存档

文章标签 ‘ORACLE’

朋友遇到一个问题,当建立一个包含varchar2(4000)的索引时,直接创建没有问题,但是如果加上online子句,则报错:
ORA-00604: error occurred at recursive SQL level 1
ORA-01450: maximum key length (3215) exceeded
这里实际上包含了两个问题:
1.索引的key到底可以有多大?因为索引的key是不可以跨越block的,所以最直接的决定因素是block size,Oracle的文档给出了一个计算公式:
DB_BLOCK_SIZE: Maximum Index Key Length:
============== =========================

2K (2048) [...]

1 26th, 2010 | Filed under 大话技术
标签:

一个数据库的同步系统,可以分为三部分:抓取变化,传输和加载。抓取数据库变化,最通常的做法是用trigger记录到表中,或者通过解析Oracle redo log中的信息来抓取。传输是将数据库变化记录到特定格式的文件中,通过网络推送到目标数据库上。加载则是指在目标数据库上应用这些变化(SQL),这里主要是讨论并行加载的实现思路。
我们通过trigger或者redo log得到了数据库变化的事务流,这个流是按照事务的提交顺序排列的,最简单的方法是在目标端按照这个事务流顺序执行,就是串行执行。这么做的最大优点是可以完全保证事务的一致性,但是缺点是性能很差。如果采用并行加载,就需要考虑事务相关性的问题,所谓事务相关性,是指两个或多个事务更新了同一条或者多条记录,他们之前存在时间上的依赖关系。如果将具有相关性的事务分在不同的并发进程上加载,可能出现后面的事务被前面的事务覆盖掉的情况,最终导致事务混乱。
我们设计一个并行加载的方法,目标是尽可能快的加载数据,保证不会产生数据混乱的情况,但是不能保证事务完全的一致性。这句话如何理解,假设两个事务不相关,A事务只更新A表,B事务只更新B表,如果在源库A事务先于B事务完成,那么在目标库可以让B事务先于A事务执行,或者两个事务并行执行,虽然事务的顺序与主库并不一致,但是数据是正确的,因为两个事务不相关。
我们如果按照事务去分拆并行的话,设计比较困难,因为涉及到事务的相关性分析。换个思路,我们可以按照数据来拆分并行,也就是把同一个事务拆分到不同的并发进程中,保证表的同一行记录的所有更改都由一个并发进程处理。按照这个思路,我们首先把事务流加载到一个队列或者一个内存结构中去,为了理解方便,我们可以认为放在了一张内存表中,这个表有以下几个字段,事务ID,表名,PK,SQL,时间序列号。首先按照不同的表分组,将不同的表的操作分配给不同的进程处理,每个并发进程按照事务提交的时间顺序来执行。比如:A事务更新A,B,C三张表的A1,B1,C1记录,B事务更新A,B,C三张表的A2,B2,C2记录,C事务更新A,B,C三张表的A3,B3,C3记录。三个事务的提交顺序是A,B,C,这时我们可以启动三个并发进程,分别处理A表,B表和C表的操作,顺序是A1,A2,A3……这样就实现了最简单的并行,虽然目标库的事务与主库并不一致,但是数据是完整和正确的。
按照表来做并行可能还不足够,如果某张表的更改量特别大,这时我们还可以进一步分组,针对同一张表中的操作再按照行(PK)分组,保证同一行的不同操作分配到同一个的并发进程处理。这里有一些小的技巧,在很多情况下,我们可以只关注某行的最后一个操作就可以了,比如某行的最后一个操作是delete,那么我们只需要执行delete,之前的操作就可以直接丢弃,如果是insert,那么我们可以在目标库先执行delete,然后再insert,针对我们自己的系统,有些表的update是全部字段更新,所以我们直接采用了merge操作,相当于对同一行的不同操作,我们做了合并处理。因为系统是自己开发的,所以可以针对我们自己的特性定制了功能。
有人说这个思路有些土,Oracle logical standby,Goldengate或者Shareplex这些商业软件是怎么做的?我之前也写过一篇文章探讨这个问题:Oracle Logical Standby SQL Apply Architecture,这些商业软件都声称自己分析了事务的相关性,可以做到并行加载,但是同样也存在事务不一致的问题,但是分析事务的相关性肯定要按照表或者行来分析,所以思路应该不会差太远,无非是他们包装得更好。
PS:这个方法并不是我想出来的,是团队的智慧。现在看起来思路挺简单,但是其实困扰了我们很长的时间。当然如果你有更好的方法,欢迎和我讨论。
–EOF–

1 7th, 2010 | Filed under 大话技术
标签:

大牛jonathan lewis在圣诞节出了一个小题目:Holiday Quiz
I have a table with one million rows, there are no indexes on the table. The table has a column called sortcode which has no nulls, and has been generated in a highly random way so that no value appears more than four times. Consider the following queries:

select sortcode
from t1
order by sortcode;
select  sortcode
from (
select [...]

12 30th, 2009 | Filed under 大话技术
标签:

普通PC本地磁盘,没有共享存储,如何实现HA?Dataguard挺好,但是存在数据丢失的可能性,而且很难做到应用透明切换。我们用ASM,Heartbeat和iSCSI可以实现一个廉价的HA方案,如下图:

用iSCSI将本地磁盘输出到对方的机器上,利用ASM的failgroup做mirror,保证数据mirror在两台不同的机器上,就算一台机器完全损坏,数据可以做到百分之百不丢失。用Heartbeat作HA探测,如果发现主机故障,则强行关闭DB和ASM,并在备机启动ASM和DB。如果使用Oracle 11g R2,还可以利用Preferred mirror read的特性,保证主库读自己的本地磁盘,而不是通过iSCSI读备机磁盘,这样可以达到更好的性能。
缺点:Heartbeat作为HA软件,我们并不是十分了解其探测机制,可能出现误判或者无法切换的情况。但是其实IBM hacmp这种HA软件一样有问题,比如Oracle hang住时,现在的hacmp根本无法探测,因为hacmp只是判断Oracle的进程在不在,而不管数据库是否活着。
我想不管什么HA软件,都无法处理所有的异常情况,我们只要有完善的监控和应对措施就可以了。比如我们现在所有的DB都有一个监控,就是定时模拟应用去更新数据库中的数据,如果发现超时或者报错,就认为数据库出现hang的情况,并发出报警。
–EOF–
另:之前我有一篇文章介绍用ASM和iSCSI搭建RAC的文章,在实际测试过程中,发现存在一些问题,因为在11g R2之前,voting disk和OCR都必须放在RAW devices上。因为没有共享存储,如果发生某台机器全部宕机,voting disk可能会丢失一部分,造成RAC的cluster机制发生误判。所以在11g R2之前,这个方案是有问题的,在11g R2中,Oracle几乎所有的东西都可以放在ASM中,这个方案也许可行,我还没有测试过。
在我写完这篇博文后,发现这个方案存在一些问题,通过iscsi将online redo输出到另外一个主机后,log file sync的响应时间需要40-60ms,这个响应时间肯定是无法接受的。现在两台主机的互连是四块千兆网卡直连,通过Linux的Multipath来管理多路径,为什么响应时间这么久,我们还在进一步查找问题。

12 10th, 2009 | Filed under 大话技术
标签: ,

在面试时经常会问一个问题,请列举出hash在数据库内部的应用,hash的原理虽然简单,但是它在数据库中可以说是无处不在。其中hash partition是hash在数据库中一个简单的应用,虽然它没有range partition那么常用,但是我们在做数据库水平拆分时,其实就是利用了hash partition的原理,利用hash函数对某个key进行运算,然后将其分布到不同的主机上,原理很简单。
我们在设计时遇到了一个问题,当分区的数量需要变化时,基于hash的原理,数据可能会从一个分区移动到另外一个分区,因为某个key在4个分区时,可能被分布在分区3,而在8个分区时,可能被分布在分区5。这样每当分区数量变化时,就需要全部重新分布数据,代价很高。
那么Oracle是怎么做的?首先可以肯定的是Oracle的hash partition在分区增加时,不需要做全部数据的重新分布。有人告诉我Oracle的hash函数比较牛,可以保证分区数量增加时,这个hash函数可以让原来的数据还在旧的分区中,而新的数据可以分布在新的分区。Oracle的函数无非就是get_hash_value或ora_hash(10g),从hash的原理上来说,这也是不可能做到的。
我们对hash partition都有一个常识,就是partition的数量最好是2的次方,也就是2,4,8,16……,否则分区会出现不分区均衡的现象,按照hash的原理,不管是几个分区,都可以做到完全均衡的,为什么会不均衡,其实答案已经出来了,Oracle为了能够增加分区,为你预留了几个看不到的分区。
假设我们有6个分区,一共8000条数据,数据的分布如下图:

hash partition不能直接增加分区,而是split当前分区,当需要增加到8个分区时,实际上是分区3和分区4分别split产生新的分区7和分区8,如下图:

Oracle如何做到分区数量增加后,其他分区的数据不受影响呢,其实很简单,Oracle在做hash运算时,预留了分区,比如6个分区,实际上是用8个分区的hash来运算的,只不过把缺少的分区的数据合并到其他分区,这样就会出现数据不均衡的情况。Oracle的公式是这样的,用等于或者大于当前分区数量的最小的一个2的N次方,比如6个分区做8个hash bucket。我们再来考虑一下2,4,8,16(2的N次方)的情况,比如要把4个分区加为5个分区,因为已经是2的N次方,所以数据会均匀分布,而且Oracle还是使用4个hash bucket。这时新增的分区5实际上把分区1 split后产生的,这时因为有5个分区了,所以会使用8个hash bucket。这时Oracle的hash函数就比较牛了,它可以保证2,4,8,16个分区时,同一个键值分布在相同的分区或者是对应可以合并的分区,看下面的SQL:
select ora_hash(‘hellodba’,1)+1 par2,ora_hash(‘hellodba’,3)+1 par4,ora_hash(‘hellodba’,7)+1 par8,ora_hash(‘hellodba’,15)+1 par16 from dual;
PAR2 PAR4 PAR8 PAR16
———- ———- ———- ———-
[...]

12 4th, 2009 | Filed under 大话技术
标签: ,

我们常用的HA方案有几种:一是用小型机和HA软件作双机热备,这种方案始终有一台设备处于空闲状态,设备利用率很低,而且必须用IBM,HP等厂商的硬件,代价昂贵。二是用Oracle的RAC来做HA,在Linux环境下,Oracle提供了全套的解决方案,是个不错的选择,不过最低也需要一套共享的存储设备。三是用Oracle DG,这种方案成本最低,但是无法做到故障时应用透明切换,我们也曾经尝试过用heartbeat配合DG failover来作一些尝试,但是在测试中发现,在极端情况下,可能存在丢失数据或者无法切换的可能性。
自从使用MySQL数据库以来,我们就一直探索MySQL的HA方案,目前应用最广泛的是用heartbeat作HA,利用MySQL双向复制技术,达到透明切换的目的。但是heartbeat并不是十分的稳定,而且切换的过程也比较长。
是否有更好的解决方案?首先要解决故障探测的问题,如果应用可以自己探测数据库状态,发现数据库出现问题时,可以切换到另外一台备机;其二主备库之间的数据同步问题,如果我们可以解析Oracle或者MySQL的日志,还原成SQL信息并应用到备机,这样就实现了logical standby或者MySQL复制的功能。利用这两个功能,我们可以实现一个更廉价更灵活的HA方案。
目前我们正在做三个工具,第一是日志解析工具,包括Oracle和MySQL,日志解析是将日志文件中的变化还原为SQL或者日志信息;第二是数据同步工具,主要负责将日志信息打包传输,并应用到目标数据库上;第三是数据库探测与路由工具,主要负责探测数据库状态,对应用做透明故障切换。
这个方案中,由于数据库不再有primary和standby之分,仅仅是应用端来作判断连接哪个数据库,所以故障切换的时间非常快,我们测试大概只需要10秒。但是数据同步可能存在一定的延时,也就是说数据库切换后,数据可能存在一定程度的丢失,但是我们可以在切换后再对数据进行补全,这个我们是可以接受的。利用这些工具,我们可以搭建出很多灵活的解决方案,并不一定要依赖IBM,Oracle的解决方案,毕竟适合我们的才是最好的方案。
目前这个方案还在开发与验证中,欢迎大家和我探讨HA这方面的问题。
–EOF–

12 2nd, 2009 | Filed under 大话技术
标签: ,

.!.
Oracle 11g的ASM有两个有意思的特性,我们看看他们能带给我们什么?
1.Fast mirror resync
原来当diskgroup中的盘发生故障时,Oracle会将这个盘标记为offline状态,并在一定的时间内从diskgroup中drop掉这块磁盘。如果disk只是临时性的故障,那么当故障恢复时,需要同步这块盘的全部内容,尤其是当某个failure group的全部磁盘都出现问题,比如我们的存储某个节点临时性断电,这时要重新build整个failure group中的所有磁盘,这个操作会非常耗费系统的资源,而是同步的过程会很长。
fast mirror resync这个特性在发生故障时,记录数据变化,然后当磁盘恢复时,只需要同步这些变化内容,让同步的时间变得很短。DISK_REPAIR_TIME这个参数控制可以恢复的时间长短,如果故障超过这个时间,Oracle将从diskgroup中drop这块盘。
比较有意思的问题,第一个是Oracle如何记录这些变化?文档中并没有明确说明,但是我猜测是用位图方式来实现,即用位图来标识哪个extent发生了变化,然后当故障恢复时同步这个extent即可,因为位图占用的空间很小,这样就可以记录很长时间的变化。第二个是如果整个磁盘都坏掉,换了一块新的磁盘,这时必须同步这个磁盘的所有内容,fast mirror resync就失效了。
2.Preferred mirror read
ASM中mirror有primary copy和secondary copy,ASM总是读primary copy的内容,但是ASM会将不同extent的primary和secondary copy放在不同的failure group中,比如extent 1的primary在failgroup1,secondary在failgroup2,而extent2则刚好相反,用这种方式来实现负载均衡。
Preferred mirror read可以控制Oracle优先读取某个failure group上的copy,这个特性在RAC上很有用,我们可以控制RAC的节点优先读取离自己最“近”的存储,我突发奇想,设计一个两节点的RAC系统,利用iscsi来共享自己的磁盘给对方,然后利用这个特性,控制每个节点去读自己的本地磁盘。
下图这个方案,我们选用两台PC server,没有共享的存储,每台PC24块盘,如果追求吞吐量,用SAS/SATA盘,如果追求IOPS,可以用ssd盘。用iscsi将本地磁盘输出给地方节点,形成共享存储,RAC节点间互连可以用直连或交换方式。ASM中分别将两个PC的磁盘定位为单独的failgroup,利用preferred mirror read,让每个节点优先读取自己的本地failgroup中的extent copy.

以上方案未经测试,纯属虚构,如果谁有兴趣,可以搭一个验证是否可行。
将山寨进行到底。
–EOF–

11 5th, 2009 | Filed under 大话技术
标签:

Oracle 11g rR2发布在即,我最关注的是Oracle ACFS(Oracle ASM cluster file system)。它将ASM扩展为cluster file system,这样ASM就不仅仅可以为Oracle数据库提供服务,而且成为了一个通用的存储解决方案。
最让人兴奋的是ACFS终于提供了snapshot功能,采用copy-on-write技术(还有一种snapshot的技术是write-on-redirect,Netapp采用这个技术,在写的性能上要比copy-on-write好),最多可以提供63份snapshot。利用这个功能,我们可以搭建出很多有意思的解决方案。
我现在的主要工作就是用Oracle,MySQL和其他技术搭建解决方案,用最低廉的成本解决现实工作中的问题。另外的工作是研究Oracle各种机制的实现原理,并且用最简单的语言描述出来,其实好多原理都可以应用在我们自己的项目中。
期待Oracle 11g R2.
–EOF–

8 27th, 2009 | Filed under 大话技术
标签:

sequential read(顺序读)一般发生在index range scan中,也被称为单块读,scattered read(离散读)一般发生在FTS中,也被称为多块读。对于sequential和scattered这两个词的含义,往往会造成一些困惑。因为从IO的角度去看,sequential read因为是单块读,在IO子系统上是离散读。而scattered read因为是多块读,在IO子系统上是顺序读。
因为所谓的sequential和scattered是从Oracle的角度去看,而不是从IO子系统的角度去看。sequential的含义是指Oracle请求IO是顺序的,比如index range scan,就必须是先读root,再读branch,然后读leaf,最后读data block,这个过程是顺序,串行和同步的。而scattered read是指Oracle请求IO是离散的,比如在做FTS时,可以向操作系统同时请求多个IO,而且不必等到返回,就可以请求下一个IO,所以是异步的过程。所以我说scattered read是局部并行,全局串行的过程。
Oracle的顺序读在IO子系统上是离散的,而Oracle的离散度在IO子系统上是连续的,之所以这么命名是因为Oracle和IO子系统站在自己的角度观察的结果。
–EOF–Christmas in South Park hd

8 25th, 2009 | Filed under 大话技术
标签:

为什么说RAC是一个好的数据仓库解决方案,但我不认为它是一个好的OLTP解决方案。因为在OLTP系统中,过多的cache fusion会大大降低系统的性能,所以Oracle也建议尽量在不同的节点部署不同的应用,尽量减少交叉访问。所以OLTP应用的RAC的节点数不会很多(一般为2-3个),因为节点越多,管理的成本就越高,目前的很多OLTP应用都是用RAC来提供HA方面的特性,OLTP应用还是采用分布式架构比较合适,指望RAC来得到线性扩展的能力不太可能。
数据仓库应用则不同,因为任务之间比较独立,在加上数据仓库的应用主要是并行计算,这样就可以充分利用RAC节点间并行处理能力,这样RAC的节点数就可以有很多,几乎可以做到线性扩展。这时新的问题出现了,我一直说Oracle RAC的最大问题在于IO吞吐量受限于共享存储,不管是中端还是高端存储,吞吐量往往受限于存储本身的架构,所以单台存储的吞吐量总是有限的。
我们能否用廉价的PC设备堆叠一个可线性扩展的存储呢?

利用Oracle ASM和iscsi,我们可以搭建一个廉价的数据仓库解决方案,底层的数据节点可以选用专门的PC服务器,现在很多厂商都有类似产品,一台PC机可以挂24块SAS/SATA磁盘,通过iscsi输出到每台数据库主机,因为RAC要求共享存储,所以我们用网络交换机把所有数据节点和数据库节点全部连起来。用Oracle ASM管理存储,利用ASM做mirror和stripe,把IO分散到所有的数据节点上,并且还可以做到动态迁移。ASM的failgroup可以分别定义在不同的数据节点上,这样就算坏掉一个数据节点,对整个系统依然不会有影响。用iscsi主要是考虑成本,当然可以把数据节点换成存储,把iscsi换成FC。
Oracle有一篇软文介绍淘宝数据仓库系统,号称全球最大的RAC系统,这套系统有20个节点,但是并没有提到存储,我们可以设想,如果采用单一存储架构,那要多大的一个存储呢?其实……
这个架构并没有经过测试,如果Oracle有兴趣的话,可以搭一个系统测试一下,如果真的是便宜量又足,能否给我一个ACE混混?
–EOF–

7 30th, 2009 | Filed under 大话技术
标签: