市面上的同步软件,基本上都是基于数据库的日志去解析,应用的。前有DCC仿照DSG占用大批券商,银行市场,后来DSG告其仿照人家技术,其实万变不离其宗,你家,我家,都是按这个解析日志的套路去做的。最近一直被log file sync所困扰。如下是我们的生产系统截图,敏感信息已经脱敏~仅作为技术讨论

数据库日志级别对REDO产生的影响_redo切换频繁

日志每秒产生约14M,逻辑读并不高,CPU 160C,DBTIME 348,log file sync和log write 都是平均等待1ms。

数据库日志级别对REDO产生的影响_log file sync_02

数据库日志级别对REDO产生的影响_主键_03

该系统的日归档增长量差不多一天1.5T

数据库日志级别对REDO产生的影响_redo切换_04

每次有应用感知的时候,总是可以抓到我们自研的一套基于数据同步的软件在跑一些sql。由此就有了今天的话题。只不过以前口说无凭,在证据面前,同步组的同事们认可相关说明,愿意帮我们去改进问题,减少提交次数。如下复现是在测试环境中进行。但是可以很好的说明问题;

数据库日志级别对REDO产生的影响_重做_05

我们的生产表,字段个数32列,我们新建测试表就以此字段个数为准,来进行相关redo产生量的评估

数据库日志级别对REDO产生的影响_log file sync_06

为了更好的理解,我们将更改数据库现在的日志级别为MIN

数据库日志级别对REDO产生的影响_重做_07

创建32个字段的测试表,并插入数据,开启统计信息观察redo产生数据量

数据库日志级别对REDO产生的影响_redo切换_08

本次插入,产生944的redo量

数据库日志级别对REDO产生的影响_redo切换频繁_09数据库日志级别对REDO产生的影响_log file sync_10

可以从自动跟踪信息中看到,本条更新产生了536的重做量。

利用日志挖掘工具看看当时日志记录的都有什么

数据库日志级别对REDO产生的影响_redo切换_11

数据库日志级别对REDO产生的影响_重做_12

更改相关日志隔离级别

数据库日志级别对REDO产生的影响_重做_13

数据库日志级别对REDO产生的影响_redo切换频繁_14

挖取当时的日志情况,是将所有的列都去产生了相关的日志

数据库日志级别对REDO产生的影响_重做_15

update "SYS"."REDO_SUM_TEST" set "T2" = 'YJF' where "T1" = 'TEST' and "T2" = 'REDO' and "T3" = 'TEST' and "T4" = 'TEST' and "T5" = 'TEST' and "T6" = 'TEST' and "T7" = 'TEST' and "T8" = 'TEST' and "T9" = 'TEST' and "T10" = 'TEST' and "T11" = 'TEST' and "T12" = 'TEST' and "T13" = 'TEST' and "T14" = 'TEST' and "T15" = 'TEST' and "T16" = 'TEST' and "T17" = 'TEST' and "T18" = 'TEST' and "T19" = 'TEST' and "T20" = 'TEST' and "T21" = 'TEST' and "T22" = 'TEST' and "T23" = 'TEST' and "T24" = 'TEST' and "T25" = 'TEST' and "T26" = 'TEST' and "T27" = 'TEST' and "T28" = 'TEST' and "T29" = 'TEST' and "T30" = 'TEST' and "T31" = 'TEST' and "T32" = 'TEST' and ROWID = 'AAAYt+AABAAAXHpAAA';

我们继续将其改成all,观察redo产生量和redo记录值

数据库日志级别对REDO产生的影响_主键_16

数据库日志级别对REDO产生的影响_redo切换_17

可以从自动跟踪信息中看到,本条更新产生了704的重做量。确实是比数据库最小日志级别要产生REDO的量要多。如果一个库里面表特别特别多的话,产生的REDO可想而知。

数据库日志级别对REDO产生的影响_重做_18

我们试试delete的时候,它是怎么捕获的;

数据库日志级别对REDO产生的影响_主键_19

数据库日志级别对REDO产生的影响_主键_20

全量SQL文本如下:

delete from "SYS"."REDO_SUM_TEST" where "T1" = 'TEST' and "T2" = 'TEST' and "T3" = 'TEST' and "T4" = 'TEST' and "T5" = 'TEST' and "T6" = 'TEST' and "T7" = 'TEST' and "T8" = 'TEST' and "T9" = 'TEST' and "T10" = 'TEST' and "T11" = 'TEST' and "T12" = 'TEST' and "T13" = 'TEST' and "T14" = 'TEST' and "T15" = 'TEST' and "T16" = 'TEST' and "T17" = 'TEST' and "T18" = 'TEST' and "T19" = 'TEST' and "T20" = 'TEST' and "T21" = 'TEST' and "T22" = 'TEST' and "T23" = 'TEST' and "T24" = 'TEST' and "T25" = 'TEST' and "T26" = 'TEST' and "T27" = 'TEST' and "T28" = 'TEST' and "T29" = 'TEST' and "T30" = 'TEST' and "T31" = 'TEST' and "T32" = 'TEST' and ROWID = 'AAAYt+AABAAAXHpAAB';

Oracle中insert、delete命令在默认情况下产生的重做记录足以表明被修改的行的每个字段在被修改前后的值是什么,insert,变更前行不存在,产生的重做记录会记载新行的每个字段的值,delete,变更后不存在,但是由于重做记录也要负责产生撤销数据块的变更,所以行被删除之前的各字段的值也记录在撤销数据块的变更矢量中,也就是insert和delete命令的重做记录中,能找到整行的所有信息。

但是update不同于insert和delete一定会涉及一行的所有字段,常常只是更改一个或几个字段,处于对性能的考虑,Oracle没必要把修改的字段的值也保存在变更矢量中,事实上是在撤销块的比昂矢量中只记载被修改的字段的更改前的值,而在数据块的变更矢量中则记载了被修改的字段的新值,同一行中其他没有被修改的字段,不会记载其修改前的值,因为没有被修改。

主键补充日志的作用是在update命令的重做记录中添加被修改行的主键字段的旧值,这是无条件式的补充日志,所谓无条件即无论主键字段本身是否被update命令修改,其旧值都会被记录。但是,不能保证每张表一定有主键。如果存在没有主键的表,则主键字段由长度最小的非空唯一索引字段代替。如果表结构中一个非空索引字段都没有,那么oracle将:将被修改行的所有字段(除了lob和long类型)的旧值都记录下来,这将导致重做记录的数据量暴涨,所以如果要启用主键补充日志,又为了维护lgwr和重做日志,每张表最好具有主键或至少一个非空唯一字段。

ALL字段补充日志和主键补充日志一样为无条件式的,无论哪个字段被update命令修改,所有字段(除了lob,long类型)的旧值都将被记录,其效果相当于启用了主键补充日志的前提下既没有主键也没有非空唯一索引字段的情况,这样几乎所有的表数据都搬到了重做日志中,不但存在当前的,历史数据也没有丢下。对恢复操作来说比较好,但是对于lgwr和磁盘空间就不是太好,一般很少启用这样的日志。

故本人大胆预测,将我们自研同步软件修改日志级别,日志量会急剧减少,且有可能生产问题也会修复。拭目以待吧各位~