背景
场景:
- 关键数据被误操作或篡改怎么办?
挑战:
- 怎么发现和定位?
- 怎么快速通知?
- 能不能记下前后变化差异?
- 能不能回退?
- 采取什么行动?
- 能不能限制?
- 能不能藏起来, 基于行或者列?
PG 解决方案:
- 发现并记下来
- 可回退
- 告状
- 拒绝执行
- 藏起来
- 细粒度权限控制
例子
1、发现并记下来:
谁干的:
- 客户端: ip, port
- 数据库端: username, dbname, ip, port, timestamp, application_name等会话特征
dml:
- update old.value, new.value
- delete old.value
- insert new.value
《PostgreSQL 触发器用法详解1》
《PostgreSQL 触发器用法详解2》
《PostgreSQL 闪回- flash back query emulate by trigger》
《PostgreSQL 跟踪记录是谁写入的,谁更新的, 什么时间点, 来源IP等》
《PostgreSQL 跟踪记录被更新了多少次, 每次更新的前后值, 》
《PostgreSQL 跟踪记录(row,tuple)的插入、更新时间- spi,moddatetime trigger》
《PostgreSQL 14 preview - System Versioned Temporal Table - flashback闪回、跟踪、审计record/row/tuple历史版本》
DDL:
- drop, truncate 回收站
《PostgreSQL Oracle 兼容性之- 事件触发器实现类似Oracle的回收站功能》
《PostgreSQL 回收站功能- 基于HOOK的recycle bin pgtrashcan》
或者使用审计:
《PostgreSQL 审计- pg_audit module》
log_statement = all
2、可回退
《PostgreSQL 最佳实践- 在线增量备份与任意时间点恢复》
《PostgreSQL 闪回- flash back query emulate by trigger》
3、可实时告状
notify
SENDMAIL
4、拒绝、忽略执行
拒绝执行: trigger 报错: raise exception
忽略执行: before trigger return null
5、藏起来
《EnterpriseDB & PostgreSQL RLS & Oracle VPD》
[ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]
6、细粒度权限控制
权限: 查询、插入、更新、删除、截断、外键、触发器
粒度: 表、列、行
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
[, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
ON [ TABLE ] table_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
[ GRANTED BY role_specification ]
CREATE POLICY name ON table_name
[ AS { PERMISSIVE | RESTRICTIVE } ]
[ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
[ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
[ USING ( using_expression ) ]
[ WITH CHECK ( check_expression ) ]