
# 账本数据库概述
#### 背景信息
账本数据库融合了区块链思想，将用户操作记录至两种历史表：用户历史表和全局区块表中。当用户创建防篡改用户表时，系统将自动为该表添加一个hash列来保存每行数据的hash摘要信息，同时在blockchain模式下会创建一张用户历史表来记录对应用户表中每条数据的变更行为；而用户对防篡改用户表的每一次修改行为将被记录到全局区块表中。由于历史表具有只可追加不可修改的特点，因此历史表记录串联起来便形成了用户对防篡改用户表的修改历史。
用户历史表命名和结构如下：
 表1用户历史表blockchain.\<schemaname\>_\<tablename\>_hist所包含的字段 
| 字段名      | 类型     | 描述                          |
|:---|:---|:---|
| rec_num  | bigint | 行级修改操作在历史表中的执行序号。           |
| hash_ins | hash16 | INSERT或UPDATE操作插入数据行的hash值。 |
| hash_del | hash16 | DELETE或UPDATE操作删除数据行的hash值。 |
| pre_hash | hash32 | 当前用户历史表的数据整体摘要。             |
   
表2hash_ins与hash_del场景对应关系 
| -      | hash_ins         | hash_del         |
|:---|:---|:---|
| INSERT | (√) 插入行的hash值。   | 空                |
| DELETE | 空                | (√) 删除行的hash值。   |
| UPDATE | (√) 新插入数据的hash值。 | (√) 删除前该行的hash值。 |
   
#### 操作步骤
1. 创建防篡改模式。 
   例如，创建防篡改模式ledgernsp。
   ```
   gaussdb=# CREATE SCHEMA ledgernsp WITH BLOCKCHAIN;
   ```
   ![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
   如果需要创建防篡改模式或更改普通模式为防篡改模式，则需设置enable_ledger参数为on。enable_ledger默认参数为off。
   
   
2. 在防篡改模式下创建防篡改用户表。 
   例如，创建防篡改用户表ledgernsp.usertable。
   ```
   gaussdb=# CREATE TABLE ledgernsp.usertable(id int, name text);
   ```
   查看防篡改用户表结构及其对应的用户历史表结构。
   ```
   gaussdb=# \d+ ledgernsp.usertable;
   gaussdb=# \d+ blockchain.ledgernsp_usertable_hist;
   ```
   执行结果如下：
   ```
   gaussdb=# \d+ ledgernsp.usertable;
                        Table "ledgernsp.usertable"
    Column     |  Type   | Modifiers | Storage  | Stats target | Description
   --------+---------+-----------+----------+--------------+-------------
    id         | integer |           | plain    |              |
    name       | text    |           | extended |              |
    hash_69dd43   | hash16  |           | plain    |              |
   Has OIDs: no
   Distribute By: HASH(id)
   Location Nodes: ALL DATANODES
   Options: orientation=row, compression=no
   History table name: ledgernsp_usertable_hist
   gaussdb=# \d+ blockchain.ledgernsp_usertable_hist;
                Table "blockchain.ledgernsp_usertable_hist"
     Column  |  Type  | Modifiers | Storage | Stats target | Description
   ----------+--------+-----------+---------+--------------+-------------
    rec_num  | bigint |           | plain   |              |
    hash_ins | hash16 |           | plain   |              |
    hash_del | hash16 |           | plain   |              |
    pre_hash | hash32 |           | plain   |              |
   Indexes:
       "gs_hist_69dd43_index" PRIMARY KEY, btree (rec_num int4_ops) TABLESPACE pg_default
   Has OIDs: no
   Distribute By: HASH(rec_num)
   Location Nodes: ALL DATANODES
   Options: internal_mask=263
   ```
   ![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
   1. 防篡改模式下仅行存表为防篡改表，临时表、外表、unlog表及非行存表均无防篡改属性。
   
   2. 防篡改表在创建时会自动增加一个用于校验的系统列，所以防篡改表单表最大列数为1599。
    
   
   
3. 修改防篡改用户表数据。 
   例如，对防篡改用户表执行INSERT、UPDATE、DELETE操作。
   ```
   gaussdb=# INSERT INTO ledgernsp.usertable VALUES(1, 'alex'), (2, 'bob'), (3, 'peter');
   INSERT 0 3
   gaussdb=# SELECT *, hash_69dd43 FROM ledgernsp.usertable ORDER BY id;
    id | name  |       hash_69dd43
   ----+-------+------------------
     1 | alex  | 1f2e543c580cb8c5
     2 | bob   | 8fcd74a8a6a4b484
     3 | peter | f51b4b1b12d0354b
   (3 rows)
   gaussdb=# UPDATE ledgernsp.usertable SET name = 'bob2' WHERE id = 2;
   UPDATE 1
   gaussdb=# SELECT *, hash_69dd43 FROM ledgernsp.usertable ORDER BY id;
    id | name  |       hash_69dd43
   ----+-------+------------------
     1 | alex  | 1f2e543c580cb8c5
     2 | bob2  | 437761affbb7c605
     3 | peter | f51b4b1b12d0354b
   (3 rows)
   gaussdb=# DELETE FROM ledgernsp.usertable WHERE id = 3;
   DELETE 1
   gaussdb=# SELECT *, hash_69dd43 FROM ledgernsp.usertable ORDER BY id;
    id | name |       hash_69dd43
   ----+------+------------------
     1 | alex | 1f2e543c580cb8c5
     2 | bob2 | 437761affbb7c605
   (2 rows)
   ```
   
   
4. 删除表和模式。 
   若要执行其他账本数据库章节的示例，请在执行完之后再执行当前步骤，否则请直接执行当前步骤。
   ```
   gaussdb=# DROP TABLE ledgernsp.usertable;
   DROP TABLE
   gaussdb=# DROP SCHEMA ledgernsp;
   DROP SCHEMA
   ```
   
   
 
