TimesTen 应用层数据库缓存学习:4. 只读缓存

在运行本文例子前,首先先执行TimesTen 应用层数据库缓存学习:2. 环境准备中的操作。

Read-only Cache Group的概念

只读缓存组如下图:

只读缓存组(Read-Only Cache Group)的cache table不能直接修改,在Oracle数据库中的数据更新后自动同步到Timesten。
TimesTen 应用层数据库缓存学习:4. 只读缓存_第1张图片

只读缓存的原理是对Oracle中需要缓存的表建立触发器来捕捉其变化

For an autorefresh cache group, TimesTen creates a change log table and trigger in the Oracle database for each cache table in the cache group. The trigger is fired for each committed insert, update, or delete operation on the cached Oracle Database table. The trigger records the primary key of the updated rows in the change log table. The cache agent periodically scans the change log table for updated keys and then joins this table with the cached Oracle Database table to get a snapshot of the latest updates.

cache table虽不能直接修改,但更新语句可以通过passthrough模式下发到Oracle执行。
如果TimesTen暂不可用,在Oracle中的更改可以暂存,待恢复正常后再同步到TimesTen。

TimesTen 应用层数据库缓存学习:4. 只读缓存_第2张图片

如上图,只读缓存组的操作通过cache agent实现,cache agent通过ttCacheUidPwdSet设置的用户名和口令连接到Oracle执行操作。
只读缓存组不需要启动replication agent,只有AWT缓存组才需要。

Read-only Cache Group的属性

从SQL Developer中,我们来看Read-only Cache Group的定义界面
TimesTen 应用层数据库缓存学习:4. 只读缓存_第3张图片

Global表示是否为cache grid,read-only缓存组不支持,因此无法勾选。
选中Dynamic,表示加载方式为Dynamic Load,否则为Explicitly Load,下面的例子中会说明区别。
Autorefresh的属性中,incremental表示根据Oracle中记录的cached table的变化日志来同步,Full表示每次都unload所有数据后在完全同步。

Incremental autorefresh mode incurs some overhead to refresh the cache group for each committed update on the cached Oracle Database tables. There is no overhead when using full autorefresh mode.

上面这句的意思是,incremental autorefresh会在Oracle中记录日志,有开销,而full模式不会。但是,由于full模式是全同步,在refresh时的开销会很大,而incremental模式在refresh时开销小。如果每天夜间才需要同步一次,full模式也是合适的选择。

refresh interval是同步的周期,太密影响性能,太疏则数据实时性差。具体取决于业务需求。
手工load/refresh时,要求refresh state为paused。手工load/refresh和autorefresh完成后,会将state改为on。refresh state设置为off或paused时,autorefresh不会执行。

准备工作

在建立cache group之前,首先配置cache grid。这里概念容易混淆,因为我们说cache group和cache grid是不同的,而这里的操作又是必需的,我们可以理解这里的配置工作为建立一个cache grid的框架,没有任何TimesTen节点attach到它上面,只是便于以后扩展。

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> call ttGridCreate ('samplegrid');
Command> call ttGridInfo;
< SAMPLEGRID, CACHEADM, Linux Intel x86, 32-bit, 11, 2, 2 >
Command> call ttGridNameSet ('samplegrid');
Command> call ttGridNameGet;
< SAMPLEGRID >

然后启动cache agent。

$ ttisql -v1 cachedb1_1122
Command> call ttCacheStart;
或者
$ ttAdmin -cacheStart cachedb1_1122
然后可以通过ttStatus查看cache agent的状态:
$ ttstatus cachedb1_1122
TimesTen status report as of Sun Apr 10 06:24:24 2016

Daemon pid 2046 port 53392 instance tt1122
No TimesTen server running
------------------------------------------------------------------------
Data store /home/oracle/app/oracle/product/TimesTen/tt1122/info/DemoDataStore/cachedb1_1122
There are 14 connections to the data store
Shared Memory KEY 0x3a41077e ID 8650765
PL/SQL Memory KEY 0x3b41077e ID 8683534 Address 0x10000000
Type            PID     Context     Connection Name              ConnID
Cache Agent     17221   0x09a41200  Handler                           2
Cache Agent     17221   0x09b70538  Timer                             3
Cache Agent     17221   0xa7a0c560  Aging                             4

Load和Refresh的区别

这时非常重要的概念,详述请参见Cache User Guide, Chapter 5, 5Cache Group Operations,Loading and refreshing a cache group

LOAD CACHE GROUP only loads committed inserts on the cached Oracle Database tables into the TimesTen cache tables. New cache instances are loaded into the cache tables, but cache instances that already exist in the cache tables are not updated or deleted even if the corresponding rows in the cached Oracle Database tables have been updated or deleted. A load operation is primarily used to initially populate a cache group.

REFRESH CACHE GROUP replaces cache instances in the TimesTen cache tables with the most current data from the cached Oracle Database tables including cache instances that are already exist in the cache tables. A refresh operation is primarily used to update the contents of a cache group with committed updates on the cached Oracle Database tables after the cache group has been initially populated.

If the cache table definitions use a WHERE clause, only rows that satisfy the WHERE clause are loaded or refreshed into the cache tables even if the LOAD CACHE GROUP or REFRESH CACHE GROUP statement does not use a WHERE clause.

To prevent a load or refresh operation from processing a large number of cache instances within a single transaction, which can greatly reduce concurrency and throughput, use the COMMIT EVERY n ROWS clause to specify a commit frequency unless you are using the WITH ID clause. If you specify COMMIT EVERY 0 ROWS, the load or refresh operation is processed in a single transaction.

Dynamic Read-Only Cache Group

$ cd $TT_HOME/quickstart/sample_scripts/cachegrid/

$ ls
create_global_awt.sql  create_local_awt.sql  create_local_dyn_ro.sql  create_local_ro.sql

$ cat create_local_dyn_ro_bak.sql 
create dynamic readonly cache group d_ro 
   autorefresh interval 1 second
from 
tthr.jobs ( job_id       varchar2(10) not null primary key,
          job_title    varchar2(35) not null,
          min_salary   number(6),
          max_salary   number(6));

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle" -f create_local_dyn_ro_bak.sql 
 5140: Could not find TTHR.JOBS in Oracle.  May not have privileges.

$ sqlplus tthr/oracle@ttorcl 

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 06:45:32 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> select * from jobs;

JOB_ID     JOB_TITLE                           MIN_SALARY MAX_SALARY
---------- ----------------------------------- ---------- ----------
AD_PRES    President                                20000      40000
AD_VP      Administration Vice President            15000      30000
AD_ASST    Administration Assistant                  3000       6000
FI_MGR     Finance Manager                           8200      16000
FI_ACCOUNT Accountant                                4200       9000
AC_MGR     Accounting Manager                        8200      16000
AC_ACCOUNT Public Accountant                         4200       9000
SA_MAN     Sales Manager                            10000      20000
SA_REP     Sales Representative                      6000      12000
PU_MAN     Purchasing Manager                        8000      15000
PU_CLERK   Purchasing Clerk                          2500       5500

JOB_ID     JOB_TITLE                           MIN_SALARY MAX_SALARY
---------- ----------------------------------- ---------- ----------
ST_MAN     Stock Manager                             5500       8500
ST_CLERK   Stock Clerk                               2000       5000
SH_CLERK   Shipping Clerk                            2500       5500
IT_PROG    Programmer                                4000      10000
MK_MAN     Marketing Manager                         9000      15000
MK_REP     Marketing Representative                  4000       9000
HR_REP     Human Resources Representative            4000       9000
PR_REP     Public Relations Representative           4500      10500

19 rows selected.

SQL> grant select on jobs to cacheadm;

Grant succeeded.
...
$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle" -f create_local_dyn_ro_bak.sql
$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten"
Command> cachegroups;

Cache Group CACHEADM.D_RO:

  Cache Group Type: Read Only (Dynamic)
  Autorefresh: Yes
  Autorefresh Mode: Incremental
  Autorefresh State: Paused
  Autorefresh Interval: 1 Second
  Autorefresh Status: ok
  Aging: LRU on

  Root Table: TTHR.JOBS
  Table Type: Read Only
# 在Oracle中,也可以看到缓存组的信息
$ cd $TT_HOME/oraclescripts
$ sqlplus cacheadm/oracle@ttorcl

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 20:40:42 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> @cacheInfo.sql
*************Autorefresh Objects Information  ***************
Host name: localhost.localdomain
Timesten datastore name:
/home/oracle/app/oracle/product/TimesTen/tt1122/info/DemoDataStore/cachedb1_1122
Cache table name: TTHR.JOBS
Change log table name: tt_06_114329_L
Number of rows in change log table: 1
Maximum logseq on the change log table: 1
Timesten has autorefreshed updates upto logseq: 1
Number of updates waiting to be autorefreshed: 0
Number of updates that has not been marked with a valid logseq: 0
****************************
*************No DDL Tracking objects are found*************

PL/SQL procedure successfully completed.

基本行为

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=tthr;pwd=timesten"
Command> desc jobs;

Table TTHR.JOBS:
  Columns:
   *JOB_ID                          VARCHAR2 (10) INLINE NOT NULL
    JOB_TITLE                       VARCHAR2 (35) INLINE NOT NULL
    MIN_SALARY                      NUMBER (6)
    MAX_SALARY                      NUMBER (6)
  Aging: LRU on
Command> select * from jobs;
Command> select * from jobs where job_id = 'FI_MGR';
 5213: Bad Oracle login error in OCISessionBegin(): ORA-01017: invalid username/password; logon denied rc = -1
 5131: Cannot connect to backend database: OracleNetServiceName = "TTORCL", uid = "TTHR", pwd is hidden, TNS_ADMIN = "/home/oracle/app/oracle/product/11.2.0/dbhome_2/network/admin", ORACLE_HOME= "/home/oracle/app/oracle/product/11.2.0/dbhome_2"
 5109: Cache Connect general error: BDB connection not open.
Command> exit
# 这点特别不能理解,明明之前用ttCacheUidPwdSet设置了用户名和口令,但在进行dynamic load时,仍然需要指定oraclepwd才能成功。
# 看一下我的KM
$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=tthr;pwd=timesten;oraclepwd=oracle"
# 下面的语句满足dynamic load要求,Dynamic Load每次只加载一行数据,而且仅当数据和主键/唯一索引完全匹配时
Command> select * from jobs where job_id = 'FI_MGR';
< FI_MGR, Finance Manager, 8200, 16000 >

# 下面的语句不会引起dynamic load
Command> select * from jobs where MIN_SALARY = 3000;
Command> delete from jobs;
 8225: Table JOBS is read only 
#只读缓存组不允许写

通过passthrough模式访问Oracle数据库

由于只读缓存组不允许修改,我们可通过passthrough模式对Oracle进行操作

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=tthr;pwd=timesten;oraclepwd=oracle"
Command> select * from jobs;
< FI_MGR, Finance Manager, 8200, 16000 >
Command> passthrough 3
Command> select * from jobs;
< AD_PRES, President, 20000, 40000 >
< AD_VP, Administration Vice President, 15000, 30000 >
< AD_ASST, Administration Assistant, 3000, 6000 >
< FI_MGR, Finance Manager, 8200, 16000 >
< FI_ACCOUNT, Accountant, 4200, 9000 >
< AC_MGR, Accounting Manager, 8200, 16000 >
< AC_ACCOUNT, Public Accountant, 4200, 9000 >
< SA_MAN, Sales Manager, 10000, 20000 >
< SA_REP, Sales Representative, 6000, 12000 >
< PU_MAN, Purchasing Manager, 8000, 15000 >
< PU_CLERK, Purchasing Clerk, 2500, 5500 >
< ST_MAN, Stock Manager, 5500, 8500 >
< ST_CLERK, Stock Clerk, 2000, 5000 >
< SH_CLERK, Shipping Clerk, 2500, 5500 >
< IT_PROG, Programmer, 4000, 10000 >
< MK_MAN, Marketing Manager, 9000, 15000 >
< MK_REP, Marketing Representative, 4000, 9000 >
< HR_REP, Human Resources Representative, 4000, 9000 >
< PR_REP, Public Relations Representative, 4500, 10500 >
Command> delete from jobs where job_id = 'FI_MGR';
 5224: Oracle foreign key violation error in OCIStmtExecute(): ORA-02292: integrity constraint (TTHR.EMP_JOB_FK) violated - child record found rc = -1
Command> update jobs set min_salary = 9000 where job_id = 'FI_MGR';
Command> commit;
Command> passthrough 0
Command> select * from jobs;
< FI_MGR, Finance Manager, 9000, 16000 >

在上例中,我们通过passthrough更改min_salary,然后更改同步到TimesTen

Dynamic Load 缓存组的Load和Refresh

以下的描述仅针对Dynamic Load 缓存组

For a dynamic cache group, a refresh operation only refreshes committed updates and deletes on the cached Oracle Database tables into the cache tables because only existing cache instances in the cache tables are refreshed. New cache instances are not loaded into the cache tables so after the refresh operation completes, the cache tables contain either the same or fewer number of cache instances. To load new cache instances into the cache tables of a dynamic cache group, use a LOAD CACHE GROUP statement or perform a dynamic load operation. See “Dynamically loading a cache instance” for more information about a dynamic load operation.

Load和Refreh的最大区别在于, Load针对的是TimesTen缓存表中没有的记录,对于已有的记录不会影响;而Refresh只更新TimesTen缓存表中已有的记录。
Load通常用于数据初始化加载,而Refresh用于更新缓存表中的数据,只有当refresh interval较长时有意义,否则autorefresh会自动更新。

以下的操作中,为了方便,我们在timesten中将tthr.jobs的SELECT权限赋予了cacheadm,在生产环境中,请不要这样做。

$ ttisql -v1 cachedb1_1122
Command> grant select on tthr.jobs to cacheadm

先来看Load操作

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> select * from tthr.jobs where job_id = 'FI_MGR';
< FI_MGR, Finance Manager, 9000, 16000 >
Command> load cache group CACHEADM.D_RO where min_salary > 10000 commit every 256 rows;
Command> select * from tthr.jobs;
< AD_PRES, President, 20000, 40000 >
< AD_VP, Administration Vice President, 15000, 30000 >
< FI_MGR, Finance Manager, 9000, 16000 >
# 这里虽然FI_MGR的最低工资并非>10000,但仍然在结果集中,我们下面修改为20000
$ sqlplus tthr/oracle@ttorcl 

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 22:25:27 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> update jobs set min_salary = 20000 where job_id = 'FI_MGR';

1 row updated.

SQL> commit;

Commit complete.

# 回到ttisql会话
Command> load cache group CACHEADM.D_RO where min_salary > 10000 commit every 256 rows;
Command> select * from tthr.jobs;
< AD_PRES, President, 20000, 40000 >
< AD_VP, Administration Vice President, 15000, 30000 >
< FI_MGR, Finance Manager, 20000, 16000 >
# 奇怪,这回FI_MGR的min_salary更新了,但事实是,这不是由于load动作引起的,而是由autorefresh引起的
# 为了看的更清楚些,我们需要将refresh interval设置更长一些或者是停止autorefresh以避免autorefresh的干扰,我们先将其设置为1小时。
Command> unload cache group CACHEADM.D_RO;
Command> select count(*) from tthr.jobs;
< 0 >
Command> alter cache group CACHEADM.D_RO set autorefresh interval 3600 seconds;
Command> exit

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=tthr;pwd=timesten;oraclepwd=oracle"
Command> passthrough 3;
Command> update jobs set min_salary = 9000 where job_id = 'FI_MGR';
Command> commit;
Command> passthrough 0;
Command> select * from jobs;
Command> select * from jobs where job_id = 'FI_MGR';
< FI_MGR, Finance Manager, 9000, 16000 >
Command> exit

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> load cache group CACHEADM.D_RO where min_salary > 10000 commit every 256 rows;
Command> select * from tthr.jobs;
< AD_PRES, President, 20000, 40000 >
< AD_VP, Administration Vice President, 15000, 30000 >
< FI_MGR, Finance Manager, 9000, 16000 >

# 在Oracle中将FI_MGR的min_salary改为20000
$ sqlplus tthr/oracle@ttorcl 

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 22:40:53 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> update jobs set min_salary = 20000 where job_id = 'FI_MGR';

1 row updated.

SQL> commit;

Commit complete.

SQL> exit

# 回到ttisql会话,再次load,由于refresh interval为1小时,此时还未发生,这时看到的结果没有autorefresh的影响。
# FI_MGR的min_salary仍不变,说明load只加载满足条件,但不在cache table中的数据
Command> load cache group CACHEADM.D_RO where min_salary > 10000 commit every 256 rows;
Command> select * from tthr.jobs ;
< AD_PRES, President, 20000, 40000 >
< AD_VP, Administration Vice President, 15000, 30000 >
< FI_MGR, Finance Manager, 9000, 16000 >
Command> unload cache group CACHEADM.D_RO;

再看Refresh操作,同样,我们需要避免autorefresh的干扰,这里我们将禁止掉autorefresh。

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> unload cache group CACHEADM.D_RO;
Command> select * from tthr.jobs;
Command> select * from tthr.jobs where job_id = 'FI_MGR';
< FI_MGR, Finance Manager, 20000, 16000 >
# 禁止autorefresh
Command> alter cache group CACHEADM.D_RO set autorefresh state paused;
# 不允许带where条件
Command> refresh cache group CACHEADM.D_RO where min_salary > 10000 commit every 256 rows;
 8304: Manual REFRESH operation with WHERE clause is not allowed on cache group CACHEADM.D_RO because it is specified as dynamic AUTOREFRESH

Command> refresh cache group CACHEADM.D_RO commit every 256 rows;

Command> select * from tthr.jobs;
< FI_MGR, Finance Manager, 20000, 16000 >

# 在Oracle中,将20000改为9000
$ sqlplus tthr/oracle@ttorcl 

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 23:04:40 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> update jobs set min_salary = 9000 where job_id = 'FI_MGR';

1 row updated.

SQL> commit;

Commit complete.

SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

# 回到ttisql会话
Command> refresh cache group CACHEADM.D_RO commit every 256 rows;
 8289: Manual LOAD/REFRESH of cache group requires AUTOREFRESH STATE to be PAUSED, but the STATE of CACHEADM.D_RO is ON. The LOAD is not allowed
# 前面refresh执行后,autorefresh会自动允许,因此我们仍需将其禁止
Command> alter cache group CACHEADM.D_RO set autorefresh state paused;
Command> refresh cache group CACHEADM.D_RO commit every 256 rows;
Command> select * from tthr.jobs;
< FI_MGR, Finance Manager, 9000, 16000 >

**这里我们应该了解了refresh和load的区别,load类似于insert语句,只加载timesten中没有的数据;而refresh类似于update,只更新timesten中已有的数据。
autorefresh会触发refresh动作。**

Explicit Load Cache Group

$ cd $TT_HOME/quickstart/sample_scripts/cachegrid/

$ ls
create_global_awt.sql  create_local_awt.sql  create_local_dyn_ro.sql  create_local_ro.sql

$ cat create_local_dyn_ro_bak.sql 
$ cat create_local_ro.sql
create readonly cache group ro 
   autorefresh 
       interval 5 seconds
       mode incremental
from
    tthr.departments (
            department_id   number(4) not null primary key,
            department_name varchar2(30) not null,
            manager_id      number(6),
            location_id     number(4))
where department_id < 100;


# 将hr.修改为tthr,加上where条件。并另存为create_local_ro_bak.sql

$ sqlplus tthr/oracle@ttorcl

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 23:42:55 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select * from departments where department_id < 100;

DEPARTMENT_ID DEPARTMENT_NAME                MANAGER_ID LOCATION_ID
------------- ------------------------------ ---------- -----------
           10 Administration                        200        1700
           20 Marketing                             201        1800
           30 Purchasing                            114        1700
           40 Human Resources                       203        2400
           50 Shipping                              121        1500
           60 IT                                    103        1400
           70 Public Relations                      204        2700
           80 Sales                                 145        2500
           90 Executive                             100        1700
9 rows selected.


SQL> grant select on departments to cacheadm;

Grant succeeded.
SQL> exit

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle" -f create_local_ro_bak.sql 
$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten"
Command> cachegroups;

Cache Group CACHEADM.RO:

  Cache Group Type: Read Only
  Autorefresh: Yes
  Autorefresh Mode: Incremental
  Autorefresh State: Paused
  Autorefresh Interval: 5 Seconds
  Autorefresh Status: ok
  Aging: No aging defined

  Root Table: TTHR.DEPARTMENTS
  Table Type: Read Only

# 在Oracle中,也可以看到缓存组的信息
$ cd $TT_HOME/oraclescripts
$ sqlplus cacheadm/oracle@ttorcl

SQL*Plus: Release 11.2.0.2.0 Production on Sun Apr 10 20:40:42 2016

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> @cacheInfo.sql
*************Autorefresh Objects Information  ***************
Host name: localhost.localdomain
Timesten datastore name:
/home/oracle/app/oracle/product/TimesTen/tt1122/info/DemoDataStore/cachedb1_1122
Cache table name: TTHR.DEPARTMENTS
Change log table name: tt_06_114326_L
Number of rows in change log table: 1
Maximum logseq on the change log table: 0
Timesten has autorefreshed updates upto logseq: -1
Number of updates waiting to be autorefreshed: 1
Number of updates that has not been marked with a valid logseq: 0
****************************
*************No DDL Tracking objects are found*************

PL/SQL procedure successfully completed.

基本行为

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=tthr;pwd=timesten"
Command> select * from departments;
Command> select * from departments where DEPARTMENT_ID = 10;
# 没有任何数据,需要手工load

缓存组的Load和Refresh

以下的操作中,为了方便,我们在timesten中将tthr.departments的SELECT权限赋予了cacheadm,在生产环境中,请不要这样做。

$ ttisql -v1 cachedb1_1122
Command> grant select on tthr.departments to cacheadm

先来看Load

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> load cache group cacheadm.ro commit every 256 rows;
Command> select count(*) from tthr.departments;
< 9 >
Command> unload cache group cacheadm.ro;
Command> select count(*) from tthr.departments;
< 0 >
Command> alter cache group CACHEADM.RO set autorefresh state paused;
# 对于非dynamic的只读缓存组,load时不允许带where条件
Command> load cache group cacheadm.ro where department_id < 50 commit every 256 rows;
 8287: Manual LOAD/RFRESH operations with WHERE or WITHID clauses are not allowed on cache group CACHEADM.RO because it is specified as AUTOREFRESH
Command> load cache group cacheadm.ro commit every 256 rows;
 8289: Manual LOAD/REFRESH of cache group requires AUTOREFRESH STATE to be PAUSED, but the STATE of CACHEADM.RO is OFF. The LOAD is not allowed
Command> alter cache group CACHEADM.RO set autorefresh state paused;
Command> load cache group cacheadm.ro commit every 256 rows;
Command> select count(*) from tthr.departments;
< 9 >
# 在cache table非空时,不允许load
Command> load cache group cacheadm.ro commit every 256 rows;
 8288: Manual LOAD of cache group CACHEADM.RO is not allowed because it is specified as AUTOREFRESH and it is not empty

再看Refresh

# 在Oracle中以tthr用户插入新记录
SQL> insert into departments values(25, 'SC', NULL, 1700);
SQL> commit;

# 在timesten中,马上可以看到这条记录
Command> select * from tthr.departments;
< 10, Administration, 200, 1700 >
< 20, Marketing, 201, 1800 >
**< 25, SC, <NULL>, 1700 >**
< 30, Purchasing, 114, 1700 >
< 40, Human Resources, 203, 2400 >
< 50, Shipping, 121, 1500 >
< 60, IT, 103, 1400 >
< 70, Public Relations, 204, 2700 >
< 80, Sales, 145, 2500 >
< 90, Executive, 100, 1700 >
# 我们没有手工执行任何Load和Refresh操作,而这条数据却同步到了TimesTen。这个结果是由于5秒一次的autorefresh导致的。
# 由此可见,Explicitly与Dynamic Load的缓存组,refresh的行为是不一样的,前者的refresh等于unload all + load all,而后者相当于update。
# 我们可以先禁止掉autorefresh后,然后看refresh的行为
$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> select * from tthr.departments;
< 10, Administration, 200, 1700 >
< 20, Marketing, 201, 1800 >
< 25, SC, <NULL>, 1700 >
< 30, Purchasing, 114, 1700 >
< 40, Human Resources, 203, 2400 >
< 50, Shipping, 121, 1500 >
< 60, IT, 103, 1400 >
< 70, Public Relations, 204, 2700 >
< 80, Sales, 145, 2500 >
< 90, Executive, 100, 1700 >
Command> alter cache group CACHEADM.RO set autorefresh state paused;
# 在Oracle中以tthr用户删除刚插入的记录
SQL> delete from departments where department_id = 25;
SQL> commit;
# 回到ttisql会话,由于autorefresh周期很长,此时数据还在
Command> select * from tthr.departments where department_id = 25;
< 25, SC, <NULL>, 1700 >
# 手工refresh,这时数据同步了
Command> refresh cache group cacheadm.ro commit every 256 rows;
Command> select * from tthr.departments where department_id = 25;

For an explicitly loaded cache group, a refresh operation is equivalent to issuing an UNLOAD CACHE GROUP statement followed by a LOAD CACHE GROUP statement on the cache group. In effect, all committed inserts, updates and deletes on the cached Oracle Database tables are refreshed into the cache tables. New cache instances may be loaded into the cache tables. Cache instances that already exist in the cache tables are updated or deleted if the corresponding rows in the cached Oracle Database tables have been updated or deleted. See “Unloading a cache group” for more information about the UNLOAD CACHE GROUP statement.

可以看到,对于Explicitly load缓存组,数据初始化时的load操作是必须的,但也只需要执行一次,手工refresh操作则相当于unload+load,开销很大,而自动refresh操作会基于日志将Oracle中发生变化的记录同步到TimesTen。

大部分时候,refresh和load这些手工操作都是不必要的, TimesTen会自动的执行autorefresh,dynamic load等操作。 本文的例子只为说明原理

只读缓存组,缓存部分行和列

缓存部分列是在定义缓存组时实现的,例如:

CREATE READONLY CACHE GROUP "RO" AUTOREFRESH MODE INCREMENTAL INTERVAL 5 MINUTES STATE PAUSED FROM "TTHR"."DEPARTMENTS" ( "DEPARTMENT_ID" NUMBER(4) NOT NULL, PRIMARY KEY("DEPARTMENT_ID") )

除了主键列必须缓存外,其它都可以不缓存

缓存部分行在定义缓存组时实现,例如

CREATE DYNAMIC READONLY CACHE GROUP "RO" AUTOREFRESH MODE INCREMENTAL INTERVAL 5 MINUTES STATE PAUSED FROM "TTHR"."DEPARTMENTS" ( "DEPARTMENT_ID" NUMBER(4) NOT NULL, "DEPARTMENT_NAME" VARCHAR2(30 BYTE) NOT NULL, "MANAGER_ID" NUMBER(6) , "LOCATION_ID" NUMBER(4) , PRIMARY KEY("DEPARTMENT_ID") ) AGING LRU OFF WHERE (departments.department_id = 1) Command> cachegroups ro Cache Group CACHEADM.RO: Cache Group Type: Read Only (Dynamic) Autorefresh: Yes Autorefresh Mode: Incremental Autorefresh State: Paused Autorefresh Interval: 5 Minutes Autorefresh Status: ok Aging: LRU off Root Table: TTHR.DEPARTMENTS Where Clause: (departments.department_id = 1) Table Type: Read Only 

root table和child table都可以加where条件:

CREATE READONLY CACHE GROUP "RO" AUTOREFRESH MODE INCREMENTAL INTERVAL 5 MINUTES STATE PAUSED FROM "TTHR"."REGIONS" ( "REGION_ID" NUMBER NOT NULL, "REGION_NAME" VARCHAR2(25 BYTE), PRIMARY KEY("REGION_ID") ) WHERE (regions.region_id < 5), "TTHR"."COUNTRIES" ( "COUNTRY_ID" CHAR(2 BYTE) NOT NULL, "COUNTRY_NAME" VARCHAR2(40 BYTE), "REGION_ID" NUMBER NOT NULL, PRIMARY KEY("COUNTRY_ID"), FOREIGN KEY("REGION_ID") REFERENCES "TTHR"."REGIONS"("REGION_ID") ) WHERE (tthr.countries.region_id < 5), "TTHR"."LOCATIONS" ( "LOCATION_ID" NUMBER(4) NOT NULL, "STREET_ADDRESS" VARCHAR2(40 BYTE), "POSTAL_CODE" VARCHAR2(12 BYTE), "CITY" VARCHAR2(30 BYTE) NOT NULL, "STATE_PROVINCE" VARCHAR2(25 BYTE), "COUNTRY_ID" CHAR(2 BYTE) NOT NULL, PRIMARY KEY("LOCATION_ID"), FOREIGN KEY("COUNTRY_ID") REFERENCES "TTHR"."COUNTRIES"("COUNTRY_ID") ) WHERE (locations.country_id > 0)

缓存部分行是在Load时实现的,例如

load cache group "CACHEADM"."RO" where department_id = 1 commit every 256 rows

但是只对dynamic read only 才有效

只读缓存的限制

参考cache user guide, chapter 4.

The cache tables on TimesTen cannot be updated directly.

这不用解释了
Only the ON DELETE CASCADE and UNIQUE HASH ON cache table attributes can be used in the cache table definitions.

A FLUSH CACHE GROUP statement cannot be issued on the cache group.

flush是从TimesTen到Oracle的手工动作,当然也不允许了

A TRUNCATE TABLE statement issued on a cached Oracle Database table is not automatically refreshed to the TimesTen cache table.

不会自动的更新,但可以通过refresh,或unload+load更新
A LOAD CACHE GROUP statement can only be issued on the cache group if the cache tables are empty, unless the cache group is dynamic.

对于explicitly load缓存组,load时,cache table必须为空
The autorefresh state must be PAUSED before you can issue a LOAD CACHE GROUP statement on the cache group, unless the cache group is dynamic, in which case the autorefresh state must be PAUSED or ON.

The LOAD CACHE GROUP statement cannot contain a WHERE clause, unless the cache group is dynamic, in which case the WHERE clause must be followed by a COMMIT EVERY n ROWS clause.
对于explicitly load缓存组,load时不能带where条件, 结合上一个条件,这时load只能用于数据初始化

The autorefresh state must be PAUSED before you can issue a REFRESH CACHE GROUP
statement on the cache group. The REFRESH CACHE GROUP statement cannot contain
a WHERE clause

All tables and columns referenced in WHERE clauses when creating, loading or
unloading the cache group must be fully qualified.

清理cache group

$ ttisql -v1 -connstr "dsn=cachedb1_1122;uid=cacheadm;pwd=timesten;oraclepwd=oracle"
Command> call ttGridDetach;
 3363: Node is not attached to a grid <-说明是cache group而非cache grid
Command> drop cache group CACHEADM.D_RO;
Command> drop cache group CACHEADM.RO;
Command> call ttcachestop;
Command> call ttGridDestroy('samplegrid');
Command> call ttGridNameGet;
< <NULL> >

参考

  • Cache User Guide, Chapter 2 - Getting Started,Performing operations on the read-only cache group
  • Cache User Guide, Chapter 4 - Defining Cache Groups,Creating a cache group
  • Cache User Guide, Chapter 5 - Cache Group Operations,Loading and refreshing a cache group

你可能感兴趣的:(readOnly,timesten,内存缓存,cachegroup)