Oracle高可用环境之DDL操作
高可用环境之DDL操作
在这之前,应该有锁与阻塞的基础知识。
DDL锁
Note:执行DDL会先commit当前会话操作,再执行DDL,即DDL是非原子性操作。
X类型锁:truncate、drop、alter table drop/add/modify等绝大部分DDl,会在表上持有X类型的TM锁。
S类型锁:online操作,会在表上持有RS类型的锁。
高可用环境下DDL操作风险分析:
1、DDL阻塞DML,引发应用问题。
2、因为修改表和字段,导致现有SQL语句错误,无法执行。
3、在有存储过程、包或Trigger的对象上执行DDL,导致这些PL/SQL对象失效而无法编译。
4、DDL操作使SQL语句重新分析,引发SQL语句执行计划改变。
5、高并发表上执行DDL,导致library cache latch的严重等待。
面临的挑战:
1、DDL阻塞DML,引发应用停顿。
2、DDL导致语句重新解析,导致执行计划改变,Latch争用。
如何应对这些问题呢?
这与我们对DDL操作本身的理解有很大关系。
对于1,事实上,DDL操作并非都是原子操作,也就是一些DDL操作是可分解的,虽然我们一般都是把它当作一个操作去做了。这就为我们减少DDL阻塞时间提供了可行性。如果我们能精确把握相应DDL操作的原理,依据Oracle本身操作规则,将阻塞DML操作的部分与不阻塞DML的部分分离出来,则可能大大减少DDL对应用的阻塞时间,因为DDL操作中不阻塞DML的部分往往占用很多的时间,从而使得整个DDL操作时间被拉长。更进一步,我们甚至可以利用Oracle本身的操作规则替代原本DDL操作所实现的内容。
对于2,DDL操作引发语句重新解析,很难避免吧,或许Oracle以后会更加智能——能自行区分是否应该invalid语句或者更加开放——提供给我们DDL操作invalid语句的开关。在这方面Oracle 11g也有所动作。
案例分析
在线增加字段,并带默认值
一般会这样操作,
SQL>alter table t_name add col_name col_type default col_value;
在11g之前,这个操作将会去修改表块中的内容,并且会在表上持有X类型的TM锁,对于表记录数很多,且业务繁忙的情况,系统将遭遇大量锁等待。
对于这个操作,实际上大量都是时间消耗在对表块内容的修改上,导致DDL操作时间被拉长。如果我们对于Oracle的操作规则足够熟悉的话,我们会发现,我们可以把这部分操作从DDL分离出去的,将整个操作分解为3步执行:
1、增加一个字段
SQL>alter table t_name add col_name col_type;
疑问:这个操作只是修改数据字典,而不修改块内容吗?
Note:当然这样操作是无法避免语句重新解析问题的。
2、修改该字段默认值
SQL>alter table t_name modify col_name default col_value;
这个操作只是标记以后的记录默认值为col_value,并不修改以前的记录。
3、修改以前的记录
批量修改
参考http://www.ixdba.com/html/y2007/m08/151-oracle-11g-ddl.html
http://www.ixdba.com/html/y2007/m08/159-oracle11g-add-column.html
在线给表增加主键活其他约束
主键约束与唯一约束
实现约束=约束+索引+数据校验
因为数据的校验是不阻塞读操作的,只有表约束的状态该表是阻塞读的,那么如果可以将索引建立与数据校验分离出去,则可以大大减少DDL阻塞时间。
参考:http://www.ixdba.com/html/y2007/m04/43-oracle-create-constrain.html
在线增加索引
面临挑战:
1、 1、常规方法创建索引,可能会阻塞应用。
2、 2、索引的增加可能导致有些语句执行计划发生改变。
3、 3、索引名称的改变导致索引相关hint失效。
参考:http://www.ixdba.com/html/y2007/m07/138-index-online-rebuild.html