=========================================介绍: ADMIN_MOVE_TABLE 过程-在线移动表
ADMIN_MOVE_TABLE存储过程将数据从一个活动表 移动到一个相同名称的新表对象中,而被移动的这个表在这个过程中是联机且可以被访问的。这个存储过程创建一个协议表(protocol table), 这个协议表由包含 与将被移动的表相关的 状态信息和配置选项 构成。这个过程的返回集是 行集合,该行集合 来自 与将要被移动的表相关的 协议表 。
这个存储过程使用下列的术语(terminology):
源表Source table 传入到存储过程参数中的原始表名称。是将被移动的表的名称。
目标表Target table 存储过程使用存储过程内部传入的表定义创建的表。源表中的所有数据都被拷贝到这个目标表中,然后这个目标表被命名成与源表相同的名称。
阶段表Staging table 一个由存储过程创建的表。这个staging table存储所有的更新——在移动表的过程中发生在源表上的update、delete和insert操作,在移动完成之后这个表被删除。
监控迁移过程: SYSTOOLS.ADMIN_MOVE_TABLE ==========================================语法:
有两种等效的方式来启动ADMIN_MOVE_TABLE存储过程:
1. 使用第一种方法(11个参数)来修改目标表的表定义的一些确定的内容。例如,如果你有一个表,表定义很大(几KB大小),但是你想做的仅仅是修改表的表空间,你可以这样做:不一定要决定需要去重建源表的整个CREATE TABLE 语句, 你只需要找出data_tbsp(数据表空间)、索引表空间和大对象表空间参数,让其他的可选参数为空。
2. 第二种方法(5个参数)让你有更多控制性和灵活性。你可以预先创建目标表,而不是让存储过程创建目标表。通过预先创建目标表,你可以创建一个使用第一种方法不能创建的表。
======================================================第一种方法的语法(11个参数):
>>-ADMIN_MOVE_TABLE--(--tabschema--,--tabname--,---------------->
>--data_tbsp--,--index_tbsp--,--lob_tbsp--,--------------------->
>--organize_by_clause--,--partkey_cols--,--data_part--,--------->
.---------. V | >--coldef--,----options-+--,--operation--)--------------------->< 这种方法常用来做表的表空间迁移: 即把一张表从一个表空间迁移到另一个表空间。 参数说明: tabschema: 表的schema, 大小写敏感 tabname: 表的name, 大小写敏感 data_tbsp :表数据要迁移到的目标表空间 index_tbsp: 表的索引要迁移到的目标表空间 lob_tbsp : 大数据对象要迁移到的目标表空间 organize_by_clause: 为表指定一个ORGNIZE BY子句(即MDC语句), 该参数有几种选项: (1). '' 或一个空格 ,目标表会参照原表的表结构,ORGNIZE BY子句和原表一致(原表没有则目标表也没有,原表有则目标表定义和原表一致)。 (最常用) (2). NULL 或 "-" ,这样目标表就不会用到ORGNIZE BY子句,不管原表有没有ORGNIZE BY子句定义。 (3). 给定 ORGNIZE BY字段的列值, 如: 'C1, C4, (C3,C1), C2' (一般用于新添加或修改ORGNIZE BY定义) (4). 从DB210.5开始还可以直接指定完全的ORGNIZE BY定义(9.7没有), 如:ORGANIZE BY INSERT TIME
partkey_cols: 指定目标表的分布键列(DISTRIBUTE KEY), DISTRIBUTE BY HASH选项, 该参数有几种选项: (1). '' 或一个空格 ,目标表会参照原表的表结构,分区键和原表一致。 (原表没有则目标表也没有,原表有则目标表定义和原表一致) (最常用) (2). NULL 或 "-" ,这样目标表就不会用到PARTITION BY RANGE定义,不管原表有没有DISTRIBUTE BY HASH选项。 (3). 给定DISTRIBUTE BY HASH选项定义的list值,如: 'C1, C2'
data_part: 指定目标表的数据分区表的分区键(partition key), PARTITION BY RANGE选项, 该参数有几种选项: (1). '' 或一个空格 ,目标表会参照原表的表结构,分区键和原表一致。 (原表没有则目标表也没有,原表有则目标表定义和原表一致) (最常用) (2). NULL 或 "-" ,这样目标表就不会用到PARTITION BY RANGE定义,不管原表有没有PARTITION BY RANGE定义。 (3). 给定PARTITION BY RANGE定义,如: '(C1) (STARTING FROM (1) EXCLUSIVE ENDING AT (1000) EVERY (100))'
coldef: 用来修改表字段的定义,包括列的数据类型,列的默认值。前提是字段必须存在,且修改的类型和原类型兼容(如char(10)改为char(20))。 如果要修改字段必须把所有字段全部写上,而不是该哪个只写哪个。 格式如: 'C1 INT, C2 INT DEFAULT 0' options: 这个输入参数是 由逗号分隔开的字符串,这个字符串定义了存储过程用到的选项。 该参数有几种选项: (1) . '' 或一个空格 ,目标表会参照原表的表结构,和原表一致。 (最常用) (2). KEEP, 会保留原表不删除,原表名字会改为类似T1AAAAVxo的名称。(可以从协议表中得到该名字) (3). COPY_USE_LOAD 包含的选项有: MESSAGES ON SERVER/COPY YES/NONRECOVERABLE等。 operation: 选择表移动的方式。 有两种调用存储过程的方法:使用MOVE命令来一次性的执行所有的操作;或者通过使用独立的命令每次执行表移动的一个步骤. 选项为: (1). MOVE: 一次性的执行整体表的移动。 Performs the entire table move (INIT, COPY, REPLAY, and SWAP operations) in one step. (最常用, 推荐) (2). INIT: 验证能够进行表移动,然后 初始化所有 在表移动过程中 需要的数据 (目标表、staging表、源表上的触发器) (3). COPY: 将内容从源表拷贝到目标表中去。在这个拷贝的阶段中发生的对源表的更改(update、delete、insert) 存储到staging table中,在拷贝阶段结束时创建新索引,除非指定了COPY_WITH_INDEXES选项。当然,如果需要的话,会在源表和目标表上创建辅助索引来改善RELAY阶段的性能。只能够在INIT阶段完成后使用COPY操作。 (4). REDIRECT: 不用中间表捕获迁移期间原表中的变化数据,直接放入到目标表。 Forwards changes directly to the target table instead of capturing the changes in the staging table.
常见用法: 1. 在线把表SVALENTI.T1迁移到新的表空间ACCOUNTING/ACCOUNT_IDX/ACCOUNT_LONG,并且修改几个字段的类型: 原表结构是'CUSTOMER VARCHAR(80), REGION CHAR(5), YEAR INTEGER, CONTENTS CLOB', ---以下把REGION CHAR(5)改成REGION CHAR(8),并在表中间加字段: IS_OK int not null default 0 CALL SYSPROC.ADMIN_MOVE_TABLE( 'SVALENTI', --tabschema 'T1', --tabname 'ACCOUNTING', --data_tbsp 'ACCOUNT_IDX', --index_tbsp 'ACCOUNT_LONG', --lob_tbsp '', --organize_by_clause '', --partkey_cols '', --data_part 'CUSTOMER VARCHAR(80), REGION CHAR(8), IS_OK int not null default 0, YEAR INTEGER, CONTENTS CLOB', ----coldef '', --options 'MOVE' --operation )
疑问: 如果在coldef中加入新字段: name char(9) not null default ''改怎么加?单引号内用单引号会报错。
2. 在线修改表的分布键为AP, DATA_PERIOD_KEY: CALL SYSPROC.ADMIN_MOVE_TABLE( 'SVALENTI', --tabschema 'T1', --tabname '', --data_tbsp '', --index_tbsp '', --lob_tbsp '', --organize_by_clause 'AP, DATA_PERIOD_KEY', --partkey_cols '', --data_part '', --coldef '', --options 'MOVE' --operation )
3. 在线修改表的数据分区键为(GEO_KEY) (STARTING FROM (1) EXCLUSIVE ENDING AT (1000) EVERY (100)) CALL SYSPROC.ADMIN_MOVE_TABLE( 'SVALENTI', --tabschema 'T1', --tabname '', --data_tbsp '', --index_tbsp '', --lob_tbsp '', --organize_by_clause '', --partkey_cols '(GEO_KEY) (STARTING FROM (1) EXCLUSIVE ENDING AT (1000) EVERY (100))', --data_part '', --coldef '', --options 'MOVE' --operation )
4. 在不使 T1 脱机的情况下,将 T1 表从模式 EBABANI 移到 ACCOUNTING 表空间中,并且在移动后保留原始表的副本。 使用 COPY_USE_LOAD 和 LOAD_MSGPATH 选项来设置装入消息文件路径。指定 DATA、INDEX 和 LONG 表空间以将表移动到新的表空间。原始表将保持类似于 ‘EBABANI’.’T1AAAAVxo’ 的名称。 CALL SYSPROC.ADMIN_MOVE_TABLE( 'EBABANI', 'T1', 'ACCOUNTING', 'ACCOUNTING', 'ACCOUNTING', '', '', '', '', 'KEEP, COPY_USE_LOAD,LOAD_MSGPATH "/home/ebabani"', 'MOVE')
=========================================================第二种方法的语法(5个参数):
>>-ADMIN_MOVE_TABLE--(--tabschema--,--tabname--,---------------->
.---------. V | >--target_tabname--,----options-+--,--operation--)------------->< 第二种方法让你有更多控制性和灵活性。你可以预先创建目标表,而不是让存储过程创建目标表。通过预先创建目标表,你可以创建一个使用第一种方法不能创建的表。 参数说明: tabschema: 原表schema tabname: 原表name target_tabname: 目标表name,目标表的约束: 目标表的schema和原表的schema必须一样; 目标表必须是空表; 目标表的表结构必须和原表一致; 类型表(typed tables), 物化查询表, staging tables, 远程表或集群表是不允许的(不管是原表还是目标表) 表不能有参考约束(reference constraints) options: 这个输入参数是由逗号分隔开的字符串,这个字符串定义了存储过程用到的选项。 该参数有几种选项: (1) . '' 或一个空格 ,目标表会参照原表的表结构,和原表一致。 (最常用) (2). KEEP, 会保留原表不删除,原表名字会改为类似T1AAAAVxo的名称。(可以从协议表中得到该名字) (3). COPY_USE_LOAD 包含的选项有: MESSAGES ON SERVER/COPY YES/NONRECOVERABLE等。 默认为NONRECOVERABLE。 operation: 选择表移动的方式。 有两种调用存储过程的方法:使用MOVE命令来一次性的执行所有的操作;或者通过使用独立的命令每次执行表移动的一个步骤. 选项为: (1). MOVE: 一次性的执行整体表的移动。 Performs the entire table move (INIT, COPY, REPLAY, and SWAP operations) in one step. (最常用, 推荐) (2). INIT: 验证能够进行表移动,然后 初始化所有 在表移动过程中 需要的数据 (目标表、staging表、源表上的触发器) (3). COPY: 将内容从源表拷贝到目标表中去。在这个拷贝的阶段中发生的对源表的更改(update、delete、insert) 存储到staging table中,在拷贝阶段结束时创建新索引,除非指定了COPY_WITH_INDEXES选项。当然,如果需要的话,会在源表和目标表上创建辅助索引来改善RELAY阶段的性能。只能够在INIT阶段完成后使用COPY操作。 (4). REDIRECT: 不用中间表捕获迁移期间原表中的变化数据,直接放入到目标表。 Forwards changes directly to the target table instead of capturing the changes in the staging table.
常用来修改一个表的表结构(如增加/减少字段)之后在不影响原表在线交易(insert/update/delete)的情况下做数据迁移: 常见用法例子: (1). 把表TEST.TEST_REORG的数据在线迁移到已存在的表TEST.TEST_REORG_NEW中,不保留源表: CALL SYSPROC.ADMIN_MOVE_TABLE( 'TEST', --tabschema: source table schema 'TEST_REORG', --tabname: source table name 'TEST_REORG_NEW', --target_tabname: 目标表的schema和原表的一样 '', --options 'MOVE') --operation 这个命令会把源表TEST.TEST_REORG的数据在线迁移到目标表 TEST.TEST_REORG_NEW中,然后把源表TEST.TEST_REORG删掉,再把目标表名字rename为源表名字。
(2). 把表TEST.TEST_REORG的数据在线迁移到已存在的表TEST.TEST_REORG_NEW中,不保留源表, 用load: CALL SYSPROC.ADMIN_MOVE_TABLE( 'TEST', --tabschema: source table schema 'TEST_REORG', --tabname: source table name 'TEST_REORG_NEW', --target_tabname: 目标表的schema和原表的一样 'COPY_USE_LOAD,LOAD_MSGPATH "/tmp/load_TEST_REORG"', --options 'MOVE') --operation 这个命令会把源表TEST.TEST_REORG的数据在线迁移到目标表 TEST.TEST_REORG_NEW中,然后把源表TEST.TEST_REORG删掉,再把目标表名字rename为源表名字。
(3).把表TEST.TEST_REORG的数据在线迁移到已存在的表TEST.TEST_REORG_NEW中,保留源表,用load: db2 "CALL SYSPROC.ADMIN_MOVE_TABLE( 'TEST', --tabschema: source table schema 'TEST_REORG', --tabname: source table name 'TEST_REORG_NEW', --target_tabname: 目标表的schema和原表的一样 'KEEP, COPY_USE_LOAD,LOAD_MSGPATH "/tmp/load_TEST_REORG"', --options 'MOVE')" --operation
db2 "CALL SYSPROC.ADMIN_MOVE_TABLE('TEST', 'TEST_REORG', 'TEST_REORG_NEW', 'KEEP, COPY_USE_LOAD,LOAD_MSGPATH "/tmp/load_TEST_REORG"', 'MOVE')"
这个命令会把源表TEST.TEST_REORG的数据在线迁移到目标表 TEST.TEST_REORG_NEW中,然后把源表TEST.TEST_REORG做rename(这里改为TEST.TEST_REORGAKQy7no),再把目标表名字rename为源表名字。 生产环境建议这样做,更安全些。 因为源表被rename的表名字含有小写字母,因此在CLP中容易识别不了,建议在交互模式下带上双引号执行: db2 => select count(*) from "TEST"."TEST_REORGAKQy7no" 以上这3个例子就比较适合解决生产上的一些不停机而修改表结构的场景, 适用于虽然两个表表结构不一样,但是可以把数据从源表加载到目标表的场景,如: 场景1: 在线交易表的字段长度要改变(如char(6)改为char(8) ), 中途不能影响源表的在线交易(如果直接alter再reorg table会影响交易)。可以建一个char(8)的目标表,然后参考以上3个例子进行操作(生产环境建议用例3). 场景2: 在表的最底部目标表比源表多了字段。也就是说我想在一个表底部加一些字段,只需要把这个加过字段的目标表建好,然后用这个存储过程加载数据并做切换即可。
==============================================该存储过程具体内部执行过程解释: ADMIN_MOVE_TABLE移动表数据的步骤可以对应到operation的几个值,分为: 1. INIT: 验证能够进行表移动,然后 初始化所有 在表移动过程中 需要的数据 (目标表、staging表、源表上的触发器) 2. COPY: 将内容从源表拷贝到目标表中去。在这个拷贝的阶段中发生的对源表的更改(update、delete、insert) 存储到staging table中,在拷贝阶段结束时创建新索引,除非指定了COPY_WITH_INDEXES选项。当然,如果需要的话,会在源表和目标表上创建辅助索引来改善RELAY阶段的性能。只能够在INIT阶段完成后使用COPY操作。 3. REPLAY: 将COPY制阶段开始以来源表中发生更改的任何行复制到目标表中。REPLAY只能在复制阶段完成后使用。也就是从copy开始那一刻,源表中再变化的数据会(用trigger)被同步到目标表。 4. SWAP: 表切换。如果用了KEEP,则源表被rename成其他表,目标表被rename成源表;如果没有用keep则源表删除,目标表被rename成源表。
知道了该存储过程的这几个阶段,如果执行失败了就好处理了。 如果联机移动失败,那么重新运行该移动: (1). 解决导致表移动失败的问题。 (2). 通过查询 SYSTOOLS.ADMIN_MOVE_TABLE 协议表以了解状态来确定表移动失败时正在进行的阶段: db2 "select substr(TABSCHEMA,1,20) TABSCHEMA, substr(TABNAME,1,20) TABNAME, substr(KEY,1,20) KEY, substr(VALUE,1,60) VALUE from SYSTOOLS.ADMIN_MOVE_TABLE where TABNAME='TEST_REORG'" 重点关注下状态值: STATUS COMPLETE (3). 再次调用存储过程,并指定适用operation选项: 如果过程的状态为 INIT,那么使用 INIT 选项。 如果过程的状态为 COPY,那么使用 COPY 选项。 如果过程的状态为 REPLAY,那么使用 REPLAY 或 SWAP 选项。 如果过程的状态为 CLEANUP,那么使用 CLEANUP 选项。 如果表的联机移动状态不是 COMPLETED 或 CLEANUP,那么可以通过对存储过程指定 CANCEL 选项来取消该移动: db2 "CALL SYSPROC.ADMIN_MOVE_TABLE('TEST', 'TEST_REORG', 'TEST_REORG_NEW', '', 'CANCEL')"
举例: This example covers a basic call to the stored procedure in order to update the compression value and remove the specific index information used for the target table copying.
First, the ADMIN_MOVE_TABLE procedure is called to start the table move process before calling the ADMIN_MOVE_TABLE_UTIL procedure in order to update or delete a value in the ADMIN_MOVE_TABLE protocol table: CALL SYSPROC.ADMIN_MOVE_TABLE('SVALENTI','T1','','','','','','','','','INIT')
Next, update the DEEP_COMPRESSION_SAMPLE value to 30720 KB: CALL SYSPROC.ADMIN_MOVE_TABLE_UTIL('SVALENTI','T1','UPSERT', 'DEEPCOMPRESSION_SAMPLE','30720')
Now, delete the COPY_INDEXSCHEMA and COPY_INDEXNAME values: CALL SYSPROC.ADMIN_MOVE_TABLE_UTIL('SVALENTI','T1','DELETE','COPY_INDEXSCHEMA','') CALL SYSPROC.ADMIN_MOVE_TABLE_UTIL('SVALENTI','T1','DELETE','COPY_INDEXNAME','')
After these changes, continue the ADMIN_MOVE_TABLE procedure using the new values in the meta table: CALL SYSPROC.ADMIN_MOVE_TABLE('SVALENTI','T1','','','','','','','','','COPY') CALL SYSPROC.ADMIN_MOVE_TABLE('SVALENTI','T1','','','','','','','','','REPLAY') CALL SYSPROC.ADMIN_MOVE_TABLE('SVALENTI','T1','','','','','','','','','SWAP')
===========================在线表迁移限制: 表迁移限制,有些情况下不支持在线表迁移过程,可以根据reason code查找错误原因,以下是一些常见的限制:
1. 原表上不能有主外键约束,主表或依赖表都不可以。可以在迁移之前先删除主外键关系,迁移完成后再重建。 2. 如果表上有时间监控器则不能迁移。 3. 如果表上有LOB, XML, LONG类型字段,则要求表上必须有唯一索引。 4. 处于set integrity pending状态的表不能迁移
---------------------参考文档: https://www.ibm.com/support/knowledgecenter/zh/SSEPGG_10.5.0/com.ibm.db2.luw.sql.rtn.doc/doc/r0055069.html https://blog.csdn.net/nayanminxing/article/details/73481166