这章将讨论不同的缓存集合类型以及怎样进行定义。
可以使用CREATE CACHE GROUP语句来创建一个缓存集合定义,包括为每个将被缓存的Oracle表分别定义缓存表。
表 3.1 显示一个简单缓存集合定义的组成。缓存集合定义的每个部分将在下面部分讨论。
表 3.1 缓存集合定义的组成
组 成 |
CREATEtypeCACHE GROUP |
owner.name |
Cache group and table attributes |
FROMtable definition |
[WHERE ...] |
[AGING ...] |
也可以使用Web浏览器通过Cache Administrator来创建缓存集合。
在CREATE CACHE GROUP语句中,缓存集合的名称标识使用如下形式:
owner.name
如果在缓存集合的名称中不指定owner,则ID或当前会话用户将作为owner。
缓存集合类型可以是系统管理或用户管理。系统管理缓存集合强制指定数据操作,而用户管理缓存集合的数据操作可以自定义。系统管理缓存集合包括:
• READONLY cache groups
• SYNCHRONOUS WRITETHROUGH (SWT) cache groups
• ASYNCHRONOUS WRITETHROUGH (AWT) cache groups
A READONLY缓存集合通过AUTOREFRESH机制进行强制缓存操作,将Oracle表中的更新应用到TimesTen。此缓存不能进行直接更新。
图 3.1 显示一个READONLY缓存集合
图3.1 READONLY缓存集合
使用CREATE READONLY CACHE GROUP语句来创建READONLY缓存集合。缺省的:
• AUTOREFRESH缓存集合属性被设置为INCREMENTAL模式。
• AUTOREFRESH INTERVAL值为5 MINUTES。
• AUTOREFRESH STATE为PAUSED。
可以使用ALTER CACHE GROUP语句来改变任何AUTOREFRESH缓存集合属性的缺省设置或完全阻止Oracle表中的更新应用到缓存中。
在创建READONLY缓存集合之前,通过使用ttCacheUidPwdSet内部程序来设置缓存管理用户ID和口令或使用带有-cacheUidPwdSet选项的ttAdmin工具。缓存管理用户将在Oracle上创建一个触发器,所以它必须拥有显示在表 4.1中关于CREATE READONLY CACHE GROUP的Oracle权限。
对于每个数据存储,缓存管理用户ID和口令只需设置一次。如果数据存储被重写或破坏,则需要重新设置缓存管理用户ID和口令。
试图在READONLY缓存集合中更新缓存的表,将导致TimesTen错误8225 “Table is read only”。但是,如果PassThrough属性被设置为2或3,DML语句也可以通过缓存传递到Oracle,并通过AUTOREFRESH再从Oracle传回到缓存集合中。在READONLY缓存集合中的passed-through语句的效果不会在包含此语句的事务中产生。只有在此事务被提交到Oracle,然后在下一次缓存的AUTOREFRESH完成时才会体现。
当使用READONLY缓存集合时,有下列限制:
• READONLY缓存集合中的表不能直接更新。
• 缓存集合和其中的表可以使用下列属性:
– AUTOREFRESH
– UNIQUE HASH ON
– ON DELETE CASCADE
• 不允许使用手动FLUSH操作。
• TRUNCATE TABLE语句不能自动刷新。
• 当使用LOAD CACHE GROUP语句时缓存集合必须为空。
• 当使用LOAD CACHE GROUP或REFRESH CACHE GROUP语句时,AUTOREFRESH STATE必须为PAUSED。
• WHERE子句中的所有字段(列和表)的引用必须完全合法。例如:user.table和user.table.column。
• LOAD CACHE GROUP和REFRESH CACHE GROUP语句不能包含WHERE子句。
• 不能指定Least recently used (LRU)老化。
此例创建一个包含customer和ordertab表的READONLY缓存集合,名为customer_orders:
CREATE READONLY CACHE GROUP customer_orders
FROM
user1.customer (custid INTEGER NOT NULL,
name VARCHAR2(100) NOT NULL,
addr VARCHAR2(100),
zip VARCHAR2(10),
region VARCHAR2(10),
PRIMARY KEY(custid)),
user1.ordertab (orderid NUMBER NOT NULL,
custid INTEGER NOT NULL,
PRIMARY KEY (orderid),
FOREIGN KEY (custid) REFERENCES CUSTOMER(custid));
SYNCHRONOUS WRITETHROUGH (SWT)缓存集合将进行强制执行:把TimesTen中被更新的缓存数据传送到Oracle。当使用CREATE SYNCHRONOUS WRITETHROUGH CACHE GROUP语句创建SWT缓存集合时,在创建缓存集合之后,缓存集合中的内容必须手动从Oracle表加载。SWT缓存集合的内容可以在需要时进行手动加载、卸载或刷新。
对SWT缓存集合的更新将被同步提交。当应用提交一个事务时,在它提交到TimesTen之前先被提交到Oracle。应用将被锁定,并且表中的行也同进被锁定,直到事务完成到TimesTen的提交。
如果到Oracle的事务提交失败,则到TimesTen的事务提交必须被回滚。如果Oracle事务成功但TimesTen事务失败,则缓存集合的数据将与Oracle数据不同步。如果产生这种情况,必须手动将缓存集合与Oracle重同步。这可能通过调用ttCachePropagateFlagSet程序先停止到Oracle的数据传递,然后重新应用此事务到TimesTen缓存集合。作为另一选择,也可以重新从Oracle加载数据。
图 3.2 显示一个SYNCHRONOUS WRITETHROUGH缓存集合。
图3.2 SYNCHRONOUS WRITETHROUGH缓存集合
当使用SWT缓存集合时,有如下限期完成:
• 缓存集合和其中的表属性中,可以使用UNIQUE HASH ON和ON DELETE CASCADE属性。
• 不允许使用手动FLUSH操作。
• 在此类型的缓存集合定义中不能显示使用WHERE子句。
• TRUNCATE TABLE语句不能应用到缓存集合的表中。
此示例为一单独Oracle表vendor创建一个SYNCHRONOUS WRITETHROUGH缓存集合,名为vendors。在缓存集合中的vendor表的更新将自动传送到Oracle。
CREATE SYNCHRONOUS WRITETHROUGH CACHE GROUP vendors
FROM
user1.vendor (vendor_id INTEGER NOT NULL,
vendor_name VARCHAR2(100) NOT NULL,
contact_name VARCHAR2(100) NOT NULL,
phone VARCHAR2(15),
street VARCHAR2(100),
city VARCHAR2(30),
state VARCHAR2(30),
zip VARCHAR2(10),
PRIMARY KEY(vendor_id));
ASYNCHRONOUS WRITETHROUGH (AWT)缓存集合与SWT缓耻集合一样强制执行同样的操作:更新TimesTen中的缓存数据,并传送到Oracle。AWT缓存集合可以提供比SWT缓存集合理快的时间响应,因为TimesTen提交的产生与Oracle的提交不同步。这就允许应用持续执行,而不必等待Oracle事务的提交完成。而且也可在Oracle数据库关闭后更新AWT缓存集合。当Oracle数据库返回到操作时,此更新将被应用到Oracle数据库。
图 3.3 显示TimesTen缓存集合的更新被异步复制到Oracle。
图3.3 ASYNCHRONOUS WRITETHROUGH缓存集合
AWT缓存集合要求包含此缓存集合的数据存储的缓存代理和复制代理都要启动。缓存代理可能加载和刷新缓存内容。缓存代理不必运行卸载此缓存。
AWT缓存集合通过CREATE ASYNCHRONOUS WRITETHROUGH CACHE GROUP语句创建。
为了使用AWT缓存集合,必须有相应的Oracle权限,并在启动缓存代理和复制代理之前使用ttCacheUidPwdSet程序设置缓存管理用户ID和口令。
当使用AWT缓存集合时,提交到TimesTen和Oracle的事务是异步的。所以当更新提交到Oracle时,应用不一定可靠。
AWT缓存集合可以如下保证:
• 不会因为TimesTen和Oracle这间的通信失败而丢失事务。
– 如果复制代理丢失到Oracle的连接,则在代理可能连接到Oracle之后,AWT将重新启动。
– 如果数据存储上的复制代理与缓存集合一起关闭,则代理将从备份重新开始并再次启动事务。
• 对于一个单独TimesTen数据存储被提交的事务被提交到Oracle的顺序与被提交到TimesTen的顺序相同。
• 如果到Oracle的事务失败,则失败将被报告在dataStoreName.awterr错误文件中。
AWT缓存集合不能保证:
• 所有在TimesTen中执行的事务都将被应用到Oracle。Oracle上执行错误将引起整个事务被回滚。例如,可能因为违反唯一约束而引起Oracle上的插入失败。产生执行错误的事务将不会再试。
• 要绝对保证Oracle的更新顺序,因为AWT不能解决更新冲突。这儿有一些例子:
– 一行首先被更新到一个AWT表并被提交。然后一些被更新的行通过Oracle传送操作并提交。AWT代理最后应用到此行的第一次更新并重新覆盖传送操作。
– 在两个独立的数据存储中(DS1, DS2),都有一个拥有相同Oracle基表的AWT表。一行在DS1中被更新并提交。一行在DS2中被更新并提交。因为缓存集合的动作是异步的,DS2中的更新也许先于DS1中的更新应用到Oracle数据库,结果是DS1中的更新覆盖DS2中的更新。
关于SWT缓存集合的限制讨论也适用于AWT缓存集合:
• 缓存集合和表的属性可以使用UNIQUE HASH ON和ON DELETE CASCADE属性。
• 不允许使用手动FLUSH操作。
• WHERE子句不能出现在此类型的缓存集合的表定义中。
• TRUNCATE TABLE语句不能应用于缓存集合的表中。
• AWT缓存表中的VARCHAR2、NVARCHAR2、VARBINARY和TT_VARCHAR列必须限制为256K字节。
下面是只对AWT缓存集合适用的另外限制:
• 在AWT缓存集合中数据存储路径名的最大长度不能超过248字符。
• 在传送更新到Oracle的过程中产生的错误和警告,将记录在一个特殊的错误文件中,并且在提交到TimesTen以后都可以一直报告。
• AWT缓存集合不允许使用在日志被关闭的数据存储中(Logging=0)。
• 在创建或删除AWT缓存集合之前,必须停止复制代理。
• 在复制代理启动之前,更新将不会从TimesTen传送到Oracle。
• 在Oracle上的更新冲突将不会被发觉并解决。当从TimesTen传送更新时将覆盖直接到Oracle基表的更新。
• 与单一条相关的SQL语句的约束检查将立即进行。例如,假设在一个AWT表中有一个唯一索引integer字段。有10条记录,并且此字段的值的范围是从1到10。发布一条增加此字段的更新语句。此语句在TimesTen中成功,但当应用到Oracle时很可能失败。原因就是TimesTen在语句结束之后检查此唯一索引约束,但当更新应用到Oracle时,此约束是在每一行都被更新之后进行检查。所以当值为1的记录被设置为2时,它将与此字段已经为2的其它行发生冲突。
• 在一个返回twosafe服务的复制计划中不能包含AWT缓存集合。
此示例为一单独表customer创建一个ASYNCHRONOUS WRITETHROUGH缓存集合,名为customers。
CREATE ASYNCHRONOUS WRITETHROUGH CACHE GROUP customers
FROM
user1.customer (custid INTEGER NOT NULL,
name VARCHAR2(100) NOT NULL,
addr VARCHAR2(100),
zip VARCHAR2(10),
PRIMARY KEY(custid));
TimesTen需要在Oracle中创建一个状态表来支持AWT。此表用来跟踪状态和最近应用到Oracle的事务。此表由CREATE ASYNCHRONOUS WRITETHROUGH CACHE GROUP语句自动创建。作为选择,也可以在创建AWT缓存集合之前,手工创建此Oracle表。
当设置AWT缓存集合时,执行下列任务:
1. 设置缓存管理用户ID和口令。
通过使用ttCacheUidPwdSet内部程序或使用带有-cacheUidPwdSet选项的ttAdmin工具来设置缓存管理用户ID和口令。
缓存管理用户将应用更新到Oracle。所以缓存管理用户帐号必须拥有相应的Oracle权限。
对于每个数据存储,缓存管理用户ID和口令只需设置一次。如果数据存储被覆盖或被破坏,则必须重新设置缓存管理用户ID和口令。
2. 创建AWT缓存集合。
使用CREATE ASYNCHRONOUS WRITETHROUGH CACHE GROUP SQL语句。
3. 启动缓存代理。
4. 启动复制代理。
创建AWT缓存集合时将自动创建复制计划以允许数据存储与Oracle数据库进行通信。此复制计划完全由TimesTen管理,并不需要用户干涉。当使用DROP CACHE GROUP来删除AWT缓存集合时,此复制计划也将被删除。
在加载缓存集合之前,不必启动复制代理,但是如果复制代理已经首先启动,最好让它执行完毕。
5. 加载缓存集合。
使用LOAD CACHE GROUP语句。
如果系统管理缓存集合(READONLY、AWT和SWT)不适合工作需要,可以使用CREATE USERMANAGED CACHE GROUP语句来创建缓存集合以实现自定义缓存操作:
• 可以通过设置AUTOREFRESH和PROPAGATE属性来定义USERMANAGED缓存集合在Oracle和TimesTen之间进行自动刷新和传送更新。两个属性同时设置以激活双向传送,这样就可以在两者之间通过互相传送即可以更新TimesTen,又可更新Oracle。
• 可以使用SQL语句来控制Oracle和TimesTen之间的数据传送。例如,可以:
– 在应用中使用FLUSH CACHE GROUP SQL语句来将TimesTen缓存集合中的更新发送至Oracle。
– 使用LOAD CACHE GROUP或REFRESH CACHE GROUP语句来将Oracle中的更新加载或刷新到TimesTen缓存中。
• 可能通过使用UNLOAD CACHE GROUP语句从用户管理缓存集合中删除所有数据或选择的数据。
• 可以在用户管理缓存集合中为每个表指定PROPAGATE或READONLY属性,以在表级上定义可写或只读操作。
这部分显示使用EATE USERMANAGED CACHE GROUP语句创建自定义缓存集合的一些示例。
例 3.1此例为一单独表customer创建一个USERMANAGED缓存集合,名为update_anywhere_customers。customer表中的更新通过“双向”彼此传送来更新TimesTen或Oracle。图 3.4 显示update_anywhere_customersUSERMANAGED缓存集合。
图3.4简单USERMANAGED缓存集合
在此例中,设置了AUTOREFRESH属性,以使此缓存集合可以每隔30秒从Oracle进行增量更新。用户是user1。表中描述的PROPAGATE属性显示TimesTen缓存中的customer表的更新将被传送到Oracle:
CREATE USERMANAGED CACHE GROUP update_anywhere_customers
AUTOREFRESH
MODE INCREMENTAL
INTERVAL 30 SECONDS
FROM
user1.customer (custid INTEGER NOT NULL,
name VARCHAR2(100) NOT NULL,
addr VARCHAR2(100),
zip VARCHAR2(10),
PRIMARY KEY(custid),
PROPAGATE);
例 3.2此例创建一个USERMANAGED缓存集合,名为western_customers,包含四个相关联的表:customer、ordertab、order_details和cust_interest。图 3.5 显示此缓存集合和它的表。
图3.5复杂USERMANAGED缓存集合
western_customers缓存集合中的每个表都有一个主键。缓存集合中的表通过关联的外键相互连接。customer表为根表,所以在缓存集合它不能引用其它表。根表包含一条WHERE子句以限制缓存中表的行数。
指定了PROPAGATE属性,以使缓存中表的任何变化在提交时将被自动传送到相应的Oracle表。
CREATE USERMANAGED CACHE GROUP western_customers
FROM
user1.customer (custid INTEGER NOT NULL,
name VARCHAR2(100) NOT NULL,
addr VARCHAR2(100),
zip VARCHAR2(10),
region VARCHAR2(10),
PRIMARY KEY(custid),
PROPAGATE)
WHERE (customer.region = 'Western'),
user1.ordertab(orderid NUMBER NOT NULL,
custid INTEGER NOT NULL,
PRIMARY KEY (orderid),
FOREIGN KEY (custid) REFERENCES customer(custid),
PROPAGATE),
user1.order_details(orderid NUMBER NOT NULL,
itemit NUMBER NOT NULL,
quantity NUMBER NOT NULL,
PRIMARY KEY (orderid, itemid),
FOREIGN KEY (orderid) REFERENCES ordertab(orderid),
PROPAGATE),
user1.cust_interest(custid INTEGER NOT NULL,
interest VARCHAR2(10) NOT NULL,
PRIMARY KEY (custid, interest),
FOREIGN KEY (custid) REFERENCES customer(custid),
PROPAGATE);
下表总结可用于CREATE CACHE GROUP语句的属性。
表 3.2 总结AUTOREFRESH缓存集合属性。
表 3.3 列出了可应用于缓存集合中单个表定义的属性。
表 3.2 完整缓存集合的属性
缓存集合属性 |
描述 |
AUTOREFRESH |
将Oracle表中产生的更新变化自动应用到TimesTen缓存。此属性可以在READONLY和USERMANAGED缓存集合中设置。 |
表 3.3 缓存集合中表的属性
缓存表属性 |
描述 |
UNIQUE HASH ON |
为被创建的表指定一个哈希索引。可以为任何类型缓存集合中的表进行设置。 |
PROPAGATE |
在提交时自动地将缓存表中的更新传送到相应的Oracle表。只能为USERMANAGED缓存类型中的表进行设置。 |
READONLY |
指定缓存集合中的表不能更新到TimesTen。只能为USERMANAGED缓存集合中的表进行设置。 |
ON DELETE CASCADE |
指定当包含被引用键的值从父表中删除时,子表中依靠外键连接的行也要被删除。可以为任何类型的缓存集合中的表进行设置。限制: • 使用PROPAGATE属性的缓存集合表。 • SWT和AWT缓存集合表。 |
AUTOREFRESH属性是READONLY和USERMANAGED缓存集合的一个选项属性。
AUTOREFRESH自动将Oracle表中的变化应用到TimesTen缓存。
TimesTen支持两种AUTOREFRESH模式:
• FULL:通过卸载内容然后再从Oracle表重新加载来刷新整个缓存集合。
• INCREMENTAL:Oracle跟踪更新情况并周期性地只更新Oracle中已经变化行到缓存集合中。此模式将使用Oracle中的专用对象来跟踪变化情况。
缺省值:
• AUTOREFRESH MODE了为 INCREMENTAL。
• AUTOREFRESH STATE 为 PAUSED。
• AUTOREFRESH INTERVAL 值为5 MINUTES。
缓存集合使用相同的自动刷新间隔在相同的时间被刷新。
AUTOREFRESH 以 INCREMENTAL模式对于Oracle中的每个更新将产生一些额外的花销来刷新缓存集合。而使用AUTOREFRESH 和 FULL模式时则没有额外的花销。
在使用AUTOREFRESH属性创建缓存集合之前,要使用ttCacheUidPwdSet内部程序或带有-cacheUidPwdSet选项的ttAdmin工具来设置缓存管理用户ID和口令。缓存管理用户将在Oracle上创建一触发器,所以它必须拥有使用AUTOREFRESH属性的READONLY缓存集合和USERMANAGED缓存集合相应的Oracle权限。
对于每个数据存储,缓存管理用户ID和口令只需要设置一次。如果数据存储被覆盖或破坏,则必须重新设置缓存管理用户ID和口令。
当使用CREATE CACHE GROUP语句创建缓存集合时,可以指定AUTOREFRESH。在创建缓存集合之后,可以使用ALTER CACHE GROUP来改变MODE、STATE和INTERVAL的设置。ALTER CACHE GROUP语句不能用于没有使用AUTOREFRESH 属性创建的缓存集合。
AUTOREFRESH产生的频率将取决于INTERVAL值。可以使用CREATE CACHE GROUP 或ALTER CACHE GROUP语句来设置AUTOREFRESH STATE为ON、OFF或PAUSED。当提交STATE设置为ON的事务时,AUTOREFRESH将由TimesTen管理。
当STATE被设置为OFF时,到Oracle表的更新将不会被捕获或记录。当状态为PAUSED时,Oracle表中的更新将被捕获并记录在Oracle中,但不会应用到TimesTen缓存集合的表中。
当一个AUTOREFRESH操作在处理中,并且试图将STATE改变为OFF或删除缓存集合时:
• 如果LockWait普通连接属性大于0,则AUTOREFRESH操作将停止。ALTER CACHE GROUP SET AUTOREFRESH STATE OFF 和 DROP CACHE GROUP 语句将优先于AUTOREFRESH操作。
• 如果LockWait普通连接属性为0,则AUTOREFRESH操作将继续。ALTER CACHE GROUP SET AUTOREFRESH STATE OFF 和 DROP CACHE GROUP 语句将失败,并产生一个锁定终止错误。
当以INCREMENTAL模式使用AUTOREFRESH时,在Oracle中发生的变化将在change log table中进行维护。在确定的环境下,在应用到TimesTen缓存集合之前,事务中的一些记录可能将从更新日志表中被清除。如果发生这种情况,Cache Connect to Oracle启动缓存集合的完全自动更新。
当使用AUTOREFRESH时有如下限制:
• 如果在Oracle基表上使用了TRUNCATE TABLE语句,则增量AUTOREFRESH将不会工作。如果Oracle基表上使用了TRUNCATE,则必须重新设置AUTOREFRESH。使用ALTER CACHE GROUP语句来将AUTOREFRESH STATE设置为PAUSED,然后手工刷新缓存集合。再发送另一条ALTER CACHE GROUP来将AUTOREFRESH STATE重新设置为ON。
• 为了使用AUTOREFRESH特性,缓存集合中的所有表必须指定为PROPAGATE或READONLY。不能使用NOT PROPAGATE属性指定AUTOREFRESH。
• 当手工加载或刷新缓存集合时,AUTOREFRESH STATE必须为PAUSED。
• 当使用LOAD CACHE GROUP语句时,缓存集合必须为空。
• WHERE 子句中引用的所有字段(列和表)必须完全合法。例如:user.table和user.table.column。
• 对于AUTOREFRESH的缓存集合的LOAD CACHE GROUP和REFRESH CACHE GROUP语句不能包含WHERE子句。
• 不能在AUTOREFRESH缓存集合中实现LRU老化。
这部分包括下列缓存表属性:
• PROPAGATE
• READONLY
• ON DELETE CASCADE
• UNIQUE HASH ON
PROPAGATE属性只能为USERMANAGED缓存集合中的表进行指定。但是,这里讨论的传送操作与同步写(SWT)缓存集合相似。
PROPAGATE指定在提交时TimesTen缓存集合中表的任何变化将被自动传送到相应的Oracle表。NOT PROPAGATE将取传送能力。
如果缓存表使用PROPAGATE属性定义,到缓存表中的更新在TimesTen提交过程中将被传送回Oracle。是以同步的方式:
1. 提交首先尝试到Oracle。如果向Oracle提交失败,则不会再向TimesTen提交,并且TimesTen事务被作上需要回滚的标记。这种方式,Oracle数据库不会遗失数据更新。
2. 如果向Oracle提交成功,将尝试向TimesTen提交。如果向TimesTen提交失败,将收到一条说明失败原因的TimesTen错误信息。
用户的操作通过连接到Oracle的应用进行提交。对于用户的登录和口令必须指定在DSN中或到TimesTen的连接串中的UID和OraclePWD属性中。
关于传送提交到Oracle,必需满足下列要求:
• 被缓存在TimesTen中的Oracle表的列必须包括此Oracle表中至少一个唯一键或主键中的所有列。组成唯一键或主键的列在Oracle必须为非NULL值的列,并且在TimesTen缓存集合中它们必须申明为主键。
这个要求的目的就是要确保在TimesTen中被更新的行之间和Oracle中原来的数据保持一对一的映射关系。确定此一对一的映射,就不会担心应用的更新会受到非缓存行的影响。
• 表的缓存版本必须有一个主键申明。
缺省地,缓存表使用NOT PROPAGATE属性被创建,以使表中的更新不会传送到Oracle。当PROPAGATE被激活时,应用有时候偶尔需要更新缓存表,但不向Oracle提交。使用ttCachePropagateFlagSet内部程序来取消它,然后重新激活传送。
当传送被取消时,可以使用FLUSH CACHE GROUP语句来选择传送插入并更新到Oracle。
当使用PROPAGATE时有如下限制:
• 如果使用PROPAGATE,它必须为缓存集合中的所有表进行指定。
• 在同一个缓存集合中,不能同时使用PROPAGATE和READONLY缓存表。
• TimesTen不会检查冲突以防止覆盖多个当前到Oracle更新的操作。基于这个原因,更新将分别在TimesTen缓存或Oracle中进行,但不是同时。
• 如果缓存集合的AUTOREFRESH被激活或在AUTOREFRESH缓存集合的拷贝中,不能为表设置NOT PROPAGATE。
• 在缓存集合被指定为PROPAGATE之后,就不能再改变此属性。
注意:对于表使用PROPAGATE属性的缓存集合,TimesTen将不会检查向表的插入和更新是否与定义缓存集合时的WHERE子句有无约束。因此不会阻止插入和更新,并且将传送到Oracle。
READONLY表属性只能为USERMANAGED缓存集合中的表进行指定。
注意:不要混淆READONLY表属性和READONLY缓存集合类型。READONLY缓存集合类型包含只读表,但READONLY表只能显示地为USERMANAGED缓存集合指定。
可以为每个缓存集合表指定READONLY表属性,以禁止TimesTen应用更新这些表。
下面是使用READONLY表属性时的限制:
• 如果使用READONLY,它必须为缓存集合中的所有表进行指定。
• 不能与PROPAGATE表属性一起指定READONLY表属性。
当创建缓存集合时,ON DELETE CASCADE表属性可以为所有缓存集合类型的表进行指定。也可以为不在缓存集合中后进行指定。
ON DELETE CASCADE表属性指定当从父表中删除包含引用键值的行时,通过外键相关联的子表中插也将被删除。根表是缓存集合中所有其它表的父表。
所有从父表到子表的方式必须是要么是“删除”或要么是“不删除”。不能父表到子表一些是删除,而另一些是不删除。对于子表的删除方式是指定ON DELETE CASCADE。
下面是使用ON DELETE CASCADE的限制:
• 对于AWT和SWT缓存集合和使用PROPAGATE属性的缓存集合表,有ON DELETE CASCADE属性的TimesTen表的外键必须是Oracle中有ON DELETE CASCADE属性的表中的外键相的相应的一个子集。在Oracle表上的ON DELETE CASCADE动作应用到TimesTen时将作为单独的删除动作。TimesTen中的ON DELETE CASCADE动作应用到Oracle时将作为一个级联操作。
• TimesTen和Oracle之间的外键匹配只是在创建缓存集合时强制进行。如果Oracle上的外键后来进行过修改,ON DELETE CASCADE将不会正常的工作。
UNIQUE HASH ON属性可以为所有缓存集合类型中的表进行指定。也可以为不在缓存集合中的表进行指定。
UNIQUE HASH ON指定在缓存集合中的一个表上创建一个哈希索引。指定在哈希索引中的列必须同样是主键中的列。
绝大多数缓存集合的基本类型是在TimesTen中缓存一个单一的Oracle表。在一个缓存集合中缓存多个表复杂的多,并要求理解另外的Cache Connect to Oracle概念。
通常情况下,每个被缓存的Oracle表至少有一个主键或非空值的唯一索引。另外,在TimesTen缓存集合表中定义的主键和唯一索引将与那些Oracle表中的相匹配。例如,如果Oracle表有主键或唯一索引列C1、C2和C3,则相应的TimesTen缓存表中的主键也应该有列C1、C2和C3。
可以为TimesTen缓存表创建任意多个非唯一索引。增加缓存表的索引将提高同样查询非缓存TimesTen表的SQL速度。不要创建与Oracle表不匹配唯一索引,因为将起唯一约束失败。
注意:Oracle临时表不能被缓存。
如下创建一个简单缓存集合定义来缓存一单一表:
CREATETYPECACHE GROUPowner.name
FROM
owner.root_table(column_list,
PRIMARY KEY(primary_key_column_list));
说明:
•owner.root_table是Oracle表或一个Oracle表私有同义词的拥有者和表名。
•column_list是一个被缓存的表的列清单和它们的数据类型。
•primary_key_column_list是一个组成主键的列的清单。
当为列选择数据类型时,要考虑Oracle列中的数据类型并为缓存集合中的表选择相应的数据类型映射。
例 3.3图 3.6 显示一个单表READONLY缓存集合,名为target_customers,缓存Oracle表customer。TimesTen缓存集合中的数据是一个更大的存储在Oracle数据中所有用户数据集的子集。
图3.6在TimesTen中缓存单个Oracle表
使用CREATE READONLY CACHE GROUP语句来创建单表缓存集合target_customers:
CREATE READONLY CACHE GROUP target_customers
FROM
user1.customer (cust_num NUMBER NOT NULL PRIMARY KEY,
region VARCHAR2(5) NOT NULL,
name VARCHAR2(80),
address VARCHAR2(255) NOT NULL);
如果多个Oracle表被缓存在同一个缓存集合中,必须定义一个根表和多个子表。在一个缓存集合中只能有一个根表。
在有多表的缓存集合中,缓存集合中的每个子表必须通过外键约束与缓存集合中的根表或另一个子表相关联。尽管在TimesTen中缓存集合中的表必须通过外键约束关联,但在Oracle实例中,这些表不一定要关联起来。缓存集合中的根表不能通过外键约束引用缓存集合中另外的任何表。缓存集合中另外所有表都是子表。
每个表的定义必须包含一个主键。每个子表也必须包括一个引用到它父表主键的外键。缓存集合中表层次可以指定子表到父表或其它子表,但缓存集合中的表不能是一个在此缓存集合中有多个父表的子表。参阅图 3.7 关于一个正确缓存集合表配置的示例。图 3.8 显示一个不正确的表配置,图 3.9 显示如何工作来解决问题。
必须在缓存集合中为每个将被包括在缓存中的Oracle表创建单独的表定义。定义在缓存集合中的表的所有者和名称必须与Oracle表的所有者和名称相匹配。可以创建一个表定义来缓存Oracle表中列的所有数据或它的一个子集。
注意:每个Oracle表可以只被定义在一个缓存集合中。不能创建多个缓存集合来缓存相同的Oracle表。
例 3.4创建一简单缓存集合定义来缓存一个根表和一个子表如下:
CREATETYPECACHE GROUPowner.name
FROM
owner.root_table(column_list,
PRIMARY KEY(primary_key_column_list)),
owner.child_table(column_list,
PRIMARY KEY(primary_key_column_list),
FOREIGN KEY(reference_column_list)
REFERENCESowner.root_table(primary_key_column_list));
说明:
•owner.root_table是Oracle表或Oracle表的私有同义词的所有者和表名。
•owner.child_table是Oracle表或Oracle表的私有同义词的所有者和表名。
•column_list是一个被缓存表中的列清单。
•primary_key_column_list是一个组成主键的列的清单。
•reference_column_list是一个child_table中引用一个外键的列的清单。
图 3.7 显示先前显示在图 3.6中的target_customers缓存集合的多表版本。
图3.7多表缓存集合
在此例中,缓存集合被扩展到缓存三个Oracle表:customer、orders和order_item。缓存集合中的数据是一个更大的存储在Oracle数据库中所有用户数据集的一个子集。target_customers缓存集合中的每个父表有一个主键(显示为粗体),通过一个相关的外键(显示为箭头)被子表引用。表customer是根表,它不能缓存集合中任何另外的表。customer表的主键是对于target_customers缓存集合的主键。orders和order_item表是子表。
例 3.5使用CREATE READONLY CACHE GROUP语句来创建target_customers多表缓存集合:
CREATE READONLY CACHE GROUP target_customers
FROM
user1.customer (cust_num NUMBER NOT NULL PRIMARY KEY,
region VARCHAR2(10) NOT NULL,
name VARCHAR2(80),
address VARCHAR2(255) NOT NULL),
user1.orders (ord_num NUMBER NOT NULL PRIMARY KEY,
cust_num NUMBER NOT NULL,
when_placed TIMESTAMP NOT NULL,
when_shipped TIMESTAMP,
FOREIGN KEY (cust_num) REFERENCES user1.customer (cust_num)),
user1.order_item (ord_num NUMBER NOT NULL,
prod_num NUMBER NOT NULL,
quantity NUMBER NOT NULL,
PRIMARY KEY (ord_num, prod_num),
FOREIGN KEY (ord_num) REFERENCES user1.orders (ord_num));
图igure 3.8 显示缓存集合中不正确的表配置。
图3.8问题:两个根表
不能在拥有customer、orders和order_item表的同一个缓存集合中定义products和inventory表。这是因为products表没有引用(直接或间接)到根表customer的外键。这就意谓着products表也被认为是一个根表,因为一个缓存集合不能同时拥有多个根表,因此无效。
为了缓存所有表,可以为products和inventory表创建第二个缓存集合,如图 3.9所示。
图3.9解决:两个独立的缓存集合
当缓存常规Oracle表时,可以在缓存集合中根据规则规定定义Oracle分区表。例如,在只读缓存集合中的分区表在Oracle中必须有一个相应的唯一非NULL值索引。用于缓存集合的分区表可以是任何样式(哈希、列表、排列或合成)的分区或子分区表。
下面是缓存Oracle分区表时的限制:
• 除非有数据丢失,在分区上的DDL操作不会影响缓存集合。例如,如果一个分区的数据被截短,AUTOREFRESH不会从相应的缓存表中删除数据。
• 缓存集合中的WHERE子句操作不引用单独的分区或子分区。例如,试图定义下列分区表user1.partitioned_table,将返回一个错误:
CREATE READONLY CACHE GROUP badcachegroup
FROM
user1.partitioned_table(ii NUMBER NOT NULL PRIMARY KEY, jj NUMBER)
WHERE ii IN (SELECT ii
FROM user1.partitioned_table PARTITION(F200402));
注意:在离线分区上试图缓存操作(如LOAD CACHE GROUP、UNLOAD
CACHE GROUP或REFRESH CACHE GROUP)将导致ORA-00376或ORA-01110错误。但是,如果分区将离线(如在一个备份操作期间),则不会产生错误,除非这时试图访问分区。
一个定义在缓存集合中的表可以引用Oracle其表的私有的Oracle同义词。实际的Oracle基表可以存在于另一个Oracle帐号中,并有一个不同的名称,但作为同义词它必须驻留在同一个Oracle服务器上。缓存集合中的表名必须是私有同义词名称,但同义词可以指向另一个公有或私有的同义词。同义词最终必须指向(直接或间接)一个表、分区表或物化视图。
包含为Oracle同义词的表定义的缓存集合可以是一个USERMANAGED、SWT或AWT缓存集合。USERMANAGED缓存集合支持LOAD CACHE GROUP、UNLOAD CACHE GROUP、REFRESH CACHE GROUP和FLUSH CACHE GROUP 操作,但不能使用AUTOREFRESH或READONLY属性配置此缓存集合。不能在READONLY缓存集合中为Oracle同义词定义表。
在使用CREATE CACHE GROUP语句为用户管理和READONLY缓存集合中的表的定义可以包含一条WHERE子句来指定搜索条件来将Oracle数据拷贝到缓存中。
另外,可以在LOAD CACHE GROUP、UNLOAD CACHE GROUP、MERGE和FLUSH CACHE GROUP语句中指定WHERE子句。一些语句,如LOAD CACHE GROUP和REFRESH CACHE GROUP,将导致连接的WHERE子句中缓存集合中的WHERE子句将先于语句中的WHERE进行计算。所有的WHERE子句将通过TimesTen解析。不要使用TimesTen不支持的Oracle SQL语法。
例 3.6此例创建一个名为western_customers的缓存集合,指定一条WHERE子句来从Oracle表customer中只缓存那些西部地区中有邮政编码的用户的相关数据:
CREATE USERMANAGED CACHE GROUP western_customers
FROM
user1.customer (custid INTEGER NOT NULL,
name VARCHAR(2100) NOT NULL,
addr VARCHAR2(100),
zip VARCHAR2(10),
region VARCHAR2(10),
PRIMARY KEY(custid),PROPAGATE)
WHERE (user1.customer.region = 'Western');
然后在LOAD CACHE GROUP语句中指定另外一条WHERE子句来只缓存来自西部地区的ID小于或等于100的用户:
LOAD CACHE GROUP western_customers WHERE (custid <= 100)
COMMIT EVERY 256 ROWS;
CREATE CACHE GROUP和LOAD CACHE GROUP 语句中的WHERE子句,在数据被加载到缓存集合之前,在Oracle上进行计算。
表 3.4 显示LOAD CACHE GROUP, UNLOAD CACHE GROUP、REFRESH CACHE GROUP和FLUSH CACHE GROUP语句的WHERE子句是否在TimesTen、Oracle或两者上都要计算。如果CREATE CACHE GROUP语句也包含一条WHERE子句,此表显示在Oracle上计算的另外的WHERE子句。
表 3.4 WHERE子句的计算
SQL语句 |
语句的WHERE子句的计算处... |
CREATE CACHE GROUP WHERE子句计算处... |
LOAD |
Oracle |
Oracle |
UNLOAD |
TimesTen |
- |
REFRESH |
TimesTen和Oracle |
Oracle |
FLUSH |
TimesTen |
- |
表 3.5 显示对每一条SQL语句的WHERE子句是否只由TimesTen或同时由TimesTen和Oracle解析。
表 3.5 WHERE子句解析
SQL语句 |
由TimesTen解析 |
由Oracle解析 |
LOAD |
Yes |
Yes |
UNLOAD |
Yes |
No |
REFRESH |
Yes |
Yes |
FLUSH |
Yes |
No |
CREATE |
Yes |
Yes |
与详细日志一起,所有面对Oracle执行的SQL语句将记录在Oracle服务器日志中。查看此日志以更好的理解缓存集合操作的机制和执行。
下面是Cache Connect to Oracle使用WHERE子句的限制:
• CREATE CACHE GROUP语句中的WHERE子句不能指定子查询,所以它们不能引用任何当前的其它表。LOAD CACHE GROUP, UNLOAD CACHE GROUP、REFRESH CACHE GROUP和FLUSH CACHE GROUP语句中的WHERE子句可以指定子查询。
• WHERE子句不能包含Oracle PARTITION扩展名。
• LOAD CACHE GROUP、REFRESH CACHE GROUP、FLUSH CACHE GROUP语句(表和同义词)中的WHERE子句只可以引用根表,除非WHERE子句包含一个子查询。
• 当创建一个多表缓存集合时,所有WHERE子句中的列名必须合法,如:user.table.column。
在缓存集合和Oracle Database之间的操作将继承此会话中使用的TimesTen全球支持的连接属性值。这些操作包括传送、加载、刷新、更新和同步写。
不直接与指定用户会话相关联的缓存集合操作将缺省使用全球支持的连接属性设置。这些操作包括自动刷新、老化和异步写。例如,这此操作使用BINARY作为NLS_SORT的值。
如果缓存集合操作使用了与全球支持的连接属性不同的值,将产生矛盾。例如,考虑下面的语句:
CREATE CACHE GROUP cachegroup1 FROM table1(
column1 NUMBER NOT NULL PRIMARY KEY,
column2 NCHAR(30))
WHERE column2 < 'string';
WHERE子句中的字符串将使用这些字符的二进制值来进行比较。这将在基于本地组装缓存集合表时,可能导致非预期结果。
为了保证WHERE子句中的字符串使用它们语言学的值来进行比较,使用CREATE CACHE GROUP语句时使用一条与面相似的WHERE子句:
CREATE CACHE GROUP cachegroup1 FROM table1(
column1 NUMBER NOT NULL PRIMARY KEY,
column2 NCHAR(30))
WHERE
NLSSORT(column2,'NLS_SORT=TCHINESE_RADICAL')
< NLSSORT('string','NLS_SORT=TCHINESE_RADICAL');
可以为缓存集合中的根表定义一个老化性质。老化性质引用老化类型和老化属性,也就是老化状态(ON或OFF)。可以指定下列之一的老化类型:基于使用或基于时间。基于使用老化将删除指定数据存储使用范围内最近使用过(LRU)的数据。基于时间老化将根据指定的数据生存期和老化处理频率来删除数据。在相同的数据存储中,可以在同一个数据存储定义基于使用和基于时间的老化,但在指定的缓存集合或表中只能定义一种老化类型。
CREATE CACHE GROUP语句中使用表定义来为新缓存集合的根表指定一个老化性质。如果表中没有定义老化性质,可以使用ALTER TABLE语句来为已存在的缓存集合中的根表增加老化性质。可以通过先删除老化性质然后再添加老化性质来改变老化性质。
老化性质只能定义在缓存集合的根表上,因为老化是基于缓存实例的。
可以为那些没在缓存集合中的表定义老化性质。
基于使用老化将保证在指定的极限范围内通过删除最近使用过(LRU)的数据来保持数据存储中可使用内存的大小。LRU老化可用于除了使用AUTOREFRESH属性的缓存集合以外的所有类型的缓存集合。
通过在CREATE CACHE GROUP语句中的表定义中使用AGING LRU子句来为一个缓存集合定义LRU老化。如果状态是ON,老化将自动开始。如果根表是数据存储中第一个拥有LRU老化性质定义的表,老化将立即开始。否则,老化将在已有LRU老化性质定义的表上发生老化时在根表上同时发生。
使用ttAgingLRUConfig内部程序来为数据存储中的所有表指定LRU老化属性。此属性将应用到有LRU老化性质的数据存储中所有的表。如果不调用ttAgingLRUConfig内部程序,则将使用属性的缺省值。
下表总结LRU老化属性:
LRU老化属性 |
描述 |
LowUsageThreshhold |
LRU老化被解除时数据存储PermSize的百分比。 |
HighUsageThreshhold |
LRU老化激活时数据存储PermSize的百分比。 |
AgingCycle |
在两个老化周期之间的分钟数。 |
在定义LRU老化性质之后,如果为AgingCycle设置了一个新值,老化的产生将基于当前时间和新的周期。例如,如果原来的周期是15分钟,并且LRU在10分钟之前已经产生,则老化预计将在5分钟之后再次发生。但是,如果将AgingCycle参数改变为30分钟,则老化将从使用新的AgingCycle值调用ttAgingLRUConfig程序之时起30分钟后发生。
如果自从上一次老化周期后一行被访问或引用,它就不符合LRU老化的条件。如果下列之一为真时,行就认为被访问或引用过:
• 行被用来建立一条SELECT语句的结果集。
• 行已经作上被更新或删除的标记。
• 行被用来建立一条INSERT SELECT语句的结果集。
使用ALTER TABLE语句来执行下列任务:
• 通过在缓存集合的根表上使用带有SET AGING {ON|OFF}子句的ALTER TABLE语句来激活或非激活老化状态。
• 通过使用带有ADD AGING LRU [ON|OFF]子句的ALTER TABLE语句来在为已存在的根表增加一LRU老化性质。
• 通过使用带有DROP AGING子句的ALTER TABLE语句来删除根表上的老化。
使用ttAgingScheduleNow内部程序来确定老化的开始。
为了将缓存集合的老化从LRU改变为基于时间,首先使用带有DROP AGING子句的ALTER TABLE语句来删除根表上的老化。然后通过使用带有ADD AGING USE子句的ALTER TABLE语句来为根表增加基于时间的老化。
基于时间老化将根据指定的数据生存期和老化处理频率从缓存集合的根表中删除数据。在CREATE CACHE GROUP语句的表定义中的AGING USE子句中定义基于时间的老化。使用带有AGING USE子句的ALTER TABLE语句来为已存在缓存集合中的根表增加一基于时间的老化性质。
AGING USE子句有一个ColumnName参数。ColumnName是用于基于时间老化的列的名称。作为简化,称呼此列为timestamp列。timestamp列必须定义如下:
• TIMESTAMP或DATE数据类型
• NOT NULL
应用将更新timestamp列的值。如果此列的值对于某些行来说是未知的,并且不想这些行被老化,则使用一个较大的缺省值来定义此例。可以在timestamp列上创建一个索引,以提高老化处理的执行速度。
注意:不能在已存在的表中增加或修改一个列,然后将它用作timestamp列,因为不能增加或修改一个列并定义它为NOT NULL。
不能从已经有基于时间老化性质的表中删除timestamp列。
在CREATE CACHE GROUP语句中的LIFETIME子句中以days、hours或minutes指定生存期。
timestamp列中的值将从SYSDATE中被减去。被截短的结果使用指定单位(minute、hour、day),并与指定的LIFETIME值进行比较。如果结果大于LIFETIME值,则行将成为老化的候选行。
使用CYCLE子句来指定系统检查行的周期以删除超过指定的生存期的数据。如果没有指定CYCLE,则每隔五分钟产生一次老化。如果指定CYCLE为0,则老化将持续产生。如果状态为ON,老化将自动开始。
使用ALTER TABLE语句来执行下列任务:
•通过使用SET AGING {ON|OFF}子句来在使用基于时间老化性质的根表上激活或非激活老化状态。
• 通过使用SET AGING CYCLE子句来在使用基于时间老化性质的根表上改变老化周期。
• 通过使用SET AGING LIFETIME子句来改变根表中生存期。
• 通过使用ADD AGING USE子句来为没有老化性质的已存在的根表增加基于时间老化。
• 通过使用DROP AGING子句来删除根表上的老化。
当老化开始时使用ttAgingScheduleNow内部程序来安排时序。
为了将缓存集合的老化从基于时间改为LRU,首先删除根表上的老化。然后使用带有ADD AGING LRU子句的ALTER TABLE语句来为根表增加LRU老化。
注意:如果要改变AUTOREFRESH缓存集合根表的属性,必须停止缓存代理。在AUTOREFRESH 缓存集合中增加、改变或删除老化之前,停止缓存代理。
通过外键关联的表必须拥有相同的老化性质。
如果LRU老化在起作用过程中并且子表中的行最近被访问过,则不管是父表还是子表中的行都将被删除。
如果基于时间老化在起作用过程中并且父表中的行已成为老化候选行,则父行和它所有的子行都将被删除。
如果表的ON DELETE CASCADE被激活,则将忽略此设置。
使用ttAgingScheduleNow内部程序来安排老化过程的时序。一旦调用内部程序老化过程就立即开始,除非已经有一个老化过程正在进行中,这种情况下,当进行中的老化完成时,新的老化才能开始。
当调用ttAgingScheduleNow时,老化过程将启动,而不管状态是否是ON或OFF。当调用ttAgingScheduleNow时要指定根表的名称。否则ttAgingScheduleNow将在数据存储中有老化定义的所有表上启动或重新启动老化,而不仅仅是缓存集合的根表。
老化过程的启动只是作为调用ttAgingScheduleNow的结果。调用ttAgingScheduleNow不会改变老化的状态。当调用ttAgingScheduleNow时如果老化的状态是OFF,则老化过程将开始,但在过程完成后它不会持续。为了继续老化,必须再次调用ttAgingScheduleNow或将老化状态改为ON。
如果老化状态已经设置为ON,则ttAgingScheduleNow将根据调用ttAgingScheduleNow的时间来重新设置老化周期。
可以控制老化行为。首先通过使用带有SET AGING OFF子句的ALTER TABLE语句来非激活老化。然后在期望的时间使用ttAgingScheduleNow来启动老化。
调用程序时,可以使用ttAgingScheduleNow并通过通过指定表名来为单一表启动或重启老化。如果不指定表名,则ttAgingScheduleNow将启动或重启有老化定义的数据存储中所有表的老化。
可以使用ttTraceMon工具来监视老化。
可以使用基于时间老化来完成缓存集合数据变化窗口。在带有变化窗口的缓存集合中,按照时序规则添加新数据和删除老数据,以使缓存只保留满足指定的时间间隔的数据。
可以通过使用增量AUTOREFRESH属性来为缓存集合数据配置一变化窗口,并指定基于时间老化性质。AUTOREFRESH操作将在Oracle中检查timestamp以决定是否将新数据刷新到缓存表中。Oracle和TimesTen的SYSDATE和时区必须一致。
不能为通过手工加载、显示加载、刷新或插入数据的其它类型的缓存集合配置变化窗口来将新数据更新到缓存集合表中。
例 3.7下面的语句使用变化窗口属性创建一个缓存集合。
CREATE READONLY CACHE GROUP cg1
AUTOREFRESH STATE ON INTERVAL 1 MINUTES
FROM t1(i NUMBER NOT NULL PRIMARY KEY,
ts TIMESTAMP NOT NULL,
c VARCHAR2(50))
AGING USE ts LIFETIME 3 HOURS CYCLE 10 MINUTES;
cg1缓存集合有1分钟的自动刷新间隔。每一分钟都会将Oracle表中的新数据更新到缓存集合中。
老化将每10分钟检查一次老数据。老化将删除大于3小时的老数据(ts < SYSDATE - 3 HOURS)。
为AUTOREFRESH间隔和LIFETIME间隔设置的参数将决定数据将在缓存中保存多长时间。小于完整生存期间隔的数据也可能被老化出缓存。例如,如果AUTOREFRESH间隔是3天,并且LIFETIME间隔为30天,当数据进入缓存时可能已经存在3天了。因此数据在27天后将从缓存中被删除。这种情况发生是因为老化是基于Oracletimestamp而不是基于TimesTentimestamp。
如果使用Oracle TimesTen In-Memory Database的Cache Connect特性,必须使用Oracle类型模式(TypeMode=0),即使缓存集合是被7.0以前的版本所定义。
如果缓存集合是被7.0以前的版本所定义,使用带有-convertCGTypes选项的ttMigrate工具来映射数据类型到用于7.0或此后的版本的数据类型。
注意如果应用使用的是本地整数数据类型,并要继续使用它们,在调用ttMigrate之前,必须改变应用为指定的TT_INTEGER、TT_SMALLINT、TT_TINYINT和TT_BIGINT。
BINARY_FLOAT和BINARY_DOUBLE被传入到Oracle Database 10g Release 1。Cache Connect支持从Oracle9i到Oracle Database 10g的Oracle客户端和服务器端。
如果需要使用BINARY_FLOAT或BINARY_DOUBLE数据类型,TimesTen推荐如下配置:
• 使用Oracle Database 10g客户端和服务器
• 将TimesTen中的BINARY_FLOAT数据映射为Oracle中BINARY_FLOAT数据
• 将TimesTen中的BINARY_DOUBLE数据映射为Oracle中的BINARY_DOUBLE数据
可以在Oracle9i和Oracle Database 10g中使用FLOAT(n)。
如果在映射TT_BINARY_FLOAT数据类型为Oracle的FLOAT(n)时,需要保持内存或提高执行速度,TimesTen推荐Oracle客户端的版本要与服务器Oracle的版本相同或较低。尽管作为推荐,也会发生下列情况:
• 在从FLOAT(n) 转换到BINARY_FLOAT和BINARY_DOUBLE时,会有数据精度的丢擒失。
• 在缓存中当Inf和NaN被定义为BINARY_FLOAT和BINARY_DOUBLE数据类型时,Inf可能被转换溢出,NaN可能被转换为0。
当为缓存集合表的列选择数据类型时,要考虑Oracle列的数据类型,并为缓存集合表中的列选择等价的数据类型。
主键和外键列级别要高于非键列。对于缓存集合表中的键列允许的数据类型映射显示在表 3.6中。
表 3.6 键列中允许的数据类型映射
Oracle数据类型 |
TimesTen数据类型 |
NUMBER(p,s) |
NUMBER(p,s) 注意:也可以使用DECIMAL(p,s)或NUMERIC(p,s)。它们是NUMBER(p,s)的别名。 |
NUMBER(p,0) INTEGER |
TT_TINYINT TT_SMALLINT TT_INTEGER TT_BIGINT INTEGER NUMBER(p,0) |
NUMBER |
TT_TINYINT TT_SMALLINT TT_INTEGER TT_BIGINT NUMBER |
CHAR(m) |
CHAR(m) |
VARCHAR2(m) |
VARCHAR2(m) |
RAW(m) |
VARBINARY(m) |
TIMESTAMP(m) |
TIMESTAMP(m) |
DATE |
DATE |
NCHAR(m) |
NCHAR(m) |
NVARCHAR2(m) |
NVARCHAR2(m) |
表 3.7 显示关于缓存集合中非键列映射的数据类型。
表 3.7 关于非键列允许的数据类型映射
Oracle数据类型 |
TimesTen数据类型 |
NUMBER(p,s) |
NUMBER(p,s) REAL FLOAT BINARY_FLOAT DOUBLE BINARY_DOUBLE |
NUMBER(p,0) INTEGER |
TT_TINYINT TT_SMALLINT TT_INTEGER TT_BIGINT INTEGER NUMBER(p,0) FLOAT BINARY_FLOAT DOUBLE BINARY_DOUBLE |
NUMBER |
TT_TINYINT TT_SMALLINT TT_INTEGER TT_BIGINT NUMBER REAL FLOAT BINARY_FLOAT DOUBLE BINARY_DOUBLE |
CHAR(m) |
CHAR(m) |
VARCHAR2(m) |
VARCHAR2(m) |
RAW(m) |
VARBINARY(m) |
LONG |
VARCHAR2(m) 注意:m可以是为此数据类型定义的范围内的任何有效值。 |
LONG RAW |
VARBINARY(m) 注意:m可以是为此数据类型定义的范围内的任何有效值。 |
TIMESTAMP(m) |
TIMESTAMP(m) |
DATE |
DATE TIMESTAMP(0) |
FLOAT(n) 注意:包括DOUBLE PRECISION和FLOAT,等于 FLOAT(126)。也包括REAL,等于FLOAT(63)。 |
FLOAT(n) BINARY_DOUBLE 注意:FLOAT(126)可以声明为DOUBLE PRECISION。FLOAT(63)可以声明为REAL。 |
BINARY_FLOAT |
BINARY_FLOAT |
BINARY_DOUBLE |
BINARY_DOUBLE |
NCHAR(m) |
NCHAR(m) |
NVARCHAR2(m) |
NVARCHAR2(m) |