目录

一.快照表是什么

二.怎么去实现

1.无软删除主表

1.1 建主表

1.2 建快照表

1.3 创建test表的trigger

2.存在软删除主表

2.1 建主表

2.2 建快照表

2.3 创建test表的trigger

三、意义


一.快照表是什么

        首先,先解释一下快照的意思,快照:顾名思义,最初的意思就是在某一时间段快速拍一张照片做记录,那拍照片的意义是什么?意义是为了让我们以后看到这个的时候,有迹可循。那么快照表的意思其实就很简单了,就是为了来记录我们之前做的一些操作。快速的记录下我们这一瞬间的操作,可以让我们在发生问题的时候可以更好的溯源。

二.怎么去实现

目前能想到的方式是两种:

1.通过Spring AOP的方式去实现,在增删改的dao层方法上做切点,当被调用时,将信息存入指定的snapshot表中(这种方式的弊端就是,如果有人在数据库中直接操作数据了,那么操作的记录不会被保存到快照表中,所以我们今天先主要讲一下第二种实现)。

2.通过数据库自带的存储过程和触发器来实现。废话不多说。贴代码

1.无软删除主表

1.1 建主表

create table test(
    id bigserial primary key,
    name text,
    created_by text,
    created_at timestamp default now(),
    updated_by text,
    updated_at timestamp default  now()
)

1.2 建快照表

create table test_snapshot(
    test_snapshot_id bigserial primary key,
    id bigint,
    name text,
    created_by text,
    created_at timestamp default now(),
    event_type text check (event_type in ('create', 'update', 'delete'))
)

1.3 创建test表的trigger

当是删除操作的时候,一定要用OLD,因为数据一旦被删除之后,用NEW.属性都是为null

DROP TRIGGER IF EXISTS test_snapshot ON test;


CREATE
OR REPLACE FUNCTION process_test_snapshot()
    RETURNS TRIGGER AS
$$
BEGIN
    IF
(TG_OP = 'DELETE') THEN
        INSERT INTO test_snapshot (id, name, created_by, created_at, event_type)
        VALUES( OLD.id, OLD.name, OLD.updated_by, OLD.updated_at, 'delete');
    ELSIF
(TG_OP = 'UPDATE') THEN
        INSERT INTO test_snapshot (id, name, created_by, created_at, event_type)
        VALUES( NEW.id, NEW.name, NEW.updated_by, NEW.updated_at, 'update');
    ELSIF
(TG_OP = 'INSERT') THEN
        INSERT INTO test_snapshot (id, name, created_by, created_at, event_type)
        VALUES( NEW.id, NEW.name, NEW.created_by, NEW.created_at, 'create');
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER test_snapshot
    AFTER INSERT OR
UPDATE OR
DELETE
ON test
    FOR EACH ROW EXECUTE FUNCTION process_test_snapshot();

2.存在软删除主表

上述的是不存在软删除的表,那么我下面会讲一下存在软删除的表该怎么去建trigger。

2.1 建主表

create table test(
    id bigserial primary key,
    name text,
    created_by text,
    created_at timestamp default now(),
    updated_by text,
    updated_at timestamp default  now(),
    deleted_by text,
    deleted_at timestamp default now()
)

2.2 建快照表

create table test_snapshot(
    test_snapshot_id bigserial primary key,
    id bigint,
    name text,
    created_by text,
    created_at timestamp default now(),
    event_type text check (event_type in ('create', 'update', 'delete'))
)

2.3 创建test表的trigger

DROP TRIGGER IF EXISTS test_snapshot ON test;


CREATE
OR REPLACE FUNCTION process_test_snapshot()
    RETURNS TRIGGER AS
$$
BEGIN
    IF
(TG_OP = 'UPDATE' AND NEW.deleted_by IS NOT NULL) THEN
        INSERT INTO test_snapshot (id, name, created_by, created_at, event_type)
        VALUES( NEW.id, NEW.name, NEW.deleted_by, NEW.deleted_at, 'delete');
    ELSIF
(TG_OP = 'UPDATE') THEN
        INSERT INTO test_snapshot (id, name, created_by, created_at, event_type)
        VALUES( NEW.id, NEW.name, NEW.updated_by, NEW.updated_at, 'update');
    ELSIF
(TG_OP = 'INSERT') THEN
        INSERT INTO test_snapshot (id, name, created_by, created_at, event_type)
        VALUES( NEW.id, NEW.name, NEW.created_by, NEW.created_at, 'create');
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER test_snapshot
    AFTER INSERT OR
UPDATE OR
DELETE
ON test
    FOR EACH ROW EXECUTE FUNCTION process_test_snapshot();

ok,到这里我们的trigger就已经创建好了。快去试试效果吧(温馨提示:批量插入的时候也是会一一添加到快照表里面去)

三、意义

我相信肯定会有朋友有疑问,为什么我们需要这么一张表,说当我们在创建一张快照表的时候,其实我们不是会经常的去查看它,使用的频次也不会那么高!!

why ? ? ? ?

确实,我们在创建一张快照表的时候,我们非常少的去看它,去使用它。但是它存在意义有几点:1.当出现问题的时候,我们可以快速的去溯源,去定位问题,比如,当一条数据被误删除了,而我们如果没有快照表的话,我们还要去日志里面去找。但是我们如果存在快照表的话,我们就可以很快的去找到被删除的数据,并且知道是谁删除的,在什么时候删除的。可以让我们快速的做一个复盘。

2.当我们不小心修改一条数据的时候,我们可以快速的在快照表中找到修改之前,这条数据应该是什么样子的,可以很快的帮助我们去复原我们想要还原的数据!!