pg回滚会不会写wal呢?
我们知道Oracle肯定会写的,来看看pg的吧
用的pg11
commit的话看到insert和commit了。
不提交的时候,我们看到有running的事务。
rollback之后,607这个事务abort了,但是也记录了wal的。
我们用logminer挖归档,直接看v$logmnr_contents视图
可以看到,上面部分delete的rollback字段是1,而且这部分是按rowid来删除的,可以肯定是回滚产生的delete记录了。最下面那部分是我执行delete,然后commit看到的redo记录,rollback部分是0,而且可以看到sql是正常的显示。
其实这个是某天客户急急忙忙让logminer挖归档看看,说是有表数据被删了,听到这话,立马判定99.99%是应用的人在胡说八道,但为了拿出证据还是挖了一下。首先当然是用闪回查询,看看时间点附近的数据,可惜回滚段太小,已经被覆盖了。那么就挖吧,挖出来一看,根本就没插进去,当时的redo就是上面提到的这样,马上就回滚了,至于为什么回滚了,oracle层面很难看出什么了。但是开发的人说,他们的日志显示程序运行没有报错,而且都是插进去其他的session查到数据了的,觉得很扯,但是他们说用了连接池,又是短连接,难道每次都用的同一个session?我能想到的只有这样了。回滚可能是commit的时候网络出了点问题,或者其他的什么。建议让他们的程序打印更详细的日志,这个事情也就这样了。审计的话,其实也可以考虑一下各种审计类工具,对重点表进行细粒度的审计。
pg的话,像oracle这样去读归档也算是一种方法吧,找到当时的归档,然后log_dump去读,再去具体分析。当前存在的wal的名字和时间可以如下查询到:
postgres=# select * from pg_ls_waldir() order by modification asc;
name | size | modification
--------------------------+----------+------------------------
000000010000000100000038 | 16777216 | 2018-11-22 16:31:53+08
000000010000000100000037 | 16777216 | 2018-11-22 16:31:53+08
00000001000000010000003B | 16777216 | 2018-11-22 16:31:54+08
00000001000000010000003A | 16777216 | 2018-11-22 16:31:54+08
000000010000000100000039 | 16777216 | 2018-11-22 16:31:54+08
00000001000000010000003D | 16777216 | 2018-11-22 16:31:55+08
00000001000000010000003C | 16777216 | 2018-11-22 16:31:55+08
00000001000000010000003E | 16777216 | 2018-11-22 16:32:56+08
00000001000000010000003F | 16777216 | 2018-11-22 16:33:05+08
000000010000000100000040 | 16777216 | 2018-11-22 16:33:12+08
000000010000000100000041 | 16777216 | 2018-11-22 16:33:19+08
000000010000000100000042 | 16777216 | 2018-11-22 16:33:28+08
000000010000000100000043 | 16777216 | 2018-11-22 16:33:36+08
000000010000000100000044 | 16777216 | 2018-11-22 16:33:43+08
000000010000000100000046 | 16777216 | 2018-11-22 16:33:52+08
000000010000000100000045 | 16777216 | 2018-11-22 16:34:01+08
000000010000000100000047 | 16777216 | 2018-11-22 16:34:16+08
000000010000000100000036 | 16777216 | 2018-11-22 16:39:25+08
(18 rows)
postgres=#
当前的归档可以如下查询:
postgres=# select * from pg_stat_archiver;
-[ RECORD 1 ]------+------------------------------
archived_count | 3
last_archived_wal | 00000001000000010000003A
last_archived_time | 2018-11-23 10:11:16.877234+08
failed_count | 0
last_failed_wal |
last_failed_time |
stats_reset | 2018-11-14 15:07:00.294068+08
postgres=#
但是好像查不到历史的归档时间和wal名字对应信息?虽然可以ls -rtl 按时间来看,但这样也未必太麻烦了吧。
如果把log_min_duration_statement设置为0日志全记录,那日志文件就太大了,oracle的alert打开ddl日志都太多了,这个设0 ,ddl和dml全都记录了的,得做好清理策略。