Redo 日志是 OceanBase 数据库用于宕机恢复以及维护多副本数据一致性的关键组件。Redo 日志是一种物理日志,它记录了数据库对于数据的全部修改历史,具体的说记录的是一次写操作后的结果。从某个持久化的数据版本开始逐条回放 Redo 日志可以还原出数据的最新版本。
1 redo log 作用
OceanBase 数据库的 Redo 日志有两个主要作用:
- 宕机恢复:与大多数主流数据库相同,OceanBase 数据库遵循 WAL(write-ahead logging)原则,在事务提交前将 Redo 日志持久化,保证事务的原子性和持久性( ACID 中的 “A” 和 “D”)。如果 observer 进程退出或所在的服务器宕机,重启 OBServer 节点会扫描并回放本地的 Redo 日志用于恢复数据。宕机时未持久化的数据会随着 Redo 日志的回放而重新产生。
- 多副本数据一致性:OceanBase 数据库采用 Multi-Paxos 协议在多个副本间同步 Redo 日志。对于事务层来说,一次 Redo 日志的写入只有同步到多数派副本上时才能认为成功。而事务的提交需要所有 Redo 日志都成功写入。最终,所有副本都会收到相同的一段 Redo 日志并回放出数据。这就保证了一个成功提交的事务的修改最终会在所有副本上生效并保持一致。Redo 日志在多个副本上的持久化使得 OceanBase 数据库可以提供更强的容灾能力。
2 查看 Redo log 参数
在安装 OceanBase 集群的时候,需要配置 2 个参数:data_disk_size 和 log_disk_size,并且OB 是预占用的策略,就是参数分配多少,就会实际占用多少空间:
obclient [oceanbase]> select TENANT_ID ,name,value,scope from `GV$OB_PARAMETERS` gop where name like 'log_disk%' and zone='zone1';
+-----------+--------------------------------------+-------+---------+
| TENANT_ID | name | value | scope |
+-----------+--------------------------------------+-------+---------+
| NULL | log_disk_percentage | 0 | CLUSTER |
| NULL | log_disk_size | 971G | CLUSTER |
| 1 | log_disk_utilization_threshold | 80 | TENANT |
| 1 | log_disk_utilization_limit_threshold | 95 | TENANT |
……
[dave@www.cndba.cn clog]$df -lh
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/obdisk-obdata 5.0T 976G 4.1T 20% /data/oceanbase/data
/dev/mapper/obdisk-obredo 1.5T 972G 565G 64% /data/oceanbase/redo
[dave@www.cndba.cn redo]$pwd
/data/oceanbase/redo
[dave@www.cndba.cn redo]$ll
total 0
drwxrwxr-x. 16 admin admin 266 Jul 6 16:31 clog
[dave@www.cndba.cn redo]$tree -L 2
.
└── clog
├── log_pool
├── tenant_1
├── tenant_1001
├── tenant_1002
├── tenant_1011
├── tenant_1012
├── tenant_1013
├── tenant_1014
├── tenant_1015
├── tenant_1016
├── tenant_1019
├── tenant_1020
├── tenant_1027
└── tenant_1028
15 directories, 0 files
[dave@www.cndba.cn redo]$
到 3 级文件就会更多一些:
├── tenant_1027
│ └── 1
└── tenant_1028
├── 1
├── 1001
├── 1002
└── 1003
3 日志文件类型
OceanBase 数据库采用了租户级别的日志流,每个分区的所有日志要求在逻辑上连续有序。机器上同一租户的所有 Tablet 产生的日志会写入到同一个日志流,日志流中的日志存在全序关系。
OceanBase 数据库的 Redo 日志文件称为 Clog,Clog 全称 Commit log,用于记录 Redo 日志的日志内容,位于 store/clog/tenant_xxxx 目录下(其中,xxxx表示租户 ID),文件编号从 0 开始并连续递增,文件 ID 不会复用,单个日志文件的大小为 64 MB。这些日志文件记录数据库中的数据所做的更改操作,提供数据持久性保证。
[dave@www.cndba.cn log]$pwd
/data/oceanbase/redo/clog/tenant_1028/1001/log
[dave@www.cndba.cn log]$ll -lh
total 20G
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 551
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 552
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 553
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 554
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 555
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 556
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 557
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 558
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 559
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 560
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 561
-rw-r--r--. 1 admin admin 64M Jul 6 19:03 562
4 日志的产生
OceanBase 数据库的每条 Redo 日志最大为 2 MB。事务在执行过程中会在事务上下文中维护历史操作,包含数据写入、上锁等操作。
在 V3.x 之前的版本中,OceanBase 数据库仅在事务提交时才会将事务上下文中保存的历史操作转换成 Redo 日志,以 2 MB 为单位提交到 Clog 模块,Clog 模块负责将日志同步到所有副本并持久化。
在 V3.x 及之后的版本中, OceanBase 数据库新增了即时写日志功能,当事务内数据超过 2 MB 时,生成 Redo 日志,提交到 Clog 模块。
以 2 MB 为单位主要是出于性能考虑,每条日志提交到 Clog 模块后需要经过 Multi-Paxos 同步到多数派,这个过程需要较多的网络通信,耗时较多。因此,相比于传统数据库,OceanBase 数据库的单条 Redo 日志聚合了多次写操作的内容。
OceanBase 数据库的一个分区可能会有 3~5 个副本,其中只有一个副本可以作为 Leader 提供写服务,产生 Redo 日志,其它副本都只能被动接收日志。
5 日志的回放
Redo 日志的回放是 OceanBase 数据库提供高可用能力的基础。日志同步到 Follower 副本后,副本会将日志按照 transaction_id 哈希到同一个线程池的不同任务队列中进行回放。
OceanBase 数据库中不同事务的 Redo 日志并行回放,同一事务的 Redo 日志串行回放,在提高回放速度的同时保证了回放的正确性。
日志在副本上回放时首先会创建出事务上下文,然后在事务上下文中还原出操作历史,并在回放到 Commit 日志时将事务提交,相当于事务在副本的镜像上又执行了一次。
6 日志容灾
通过回放 Redo 日志,副本最终会将 Leader 上执行过的事务重新执行一遍,获得和 Leader 一致的数据状态。
当某一分区的 Leader 所在的机器发生故障或由于负载过高无法提供服务时,可以重新将另一个机器上的副本选为新的 Leader。因为它们拥有相同的日志和数据,新 Leader 可以继续提供服务。只要发生故障的副本不超过一半,OceanBase 数据库都可以持续提供服务。发生故障的副本在重启后会重新回放日志,还原出未持久化的数据,最终会和 Leader 保持一致的状态。
对于传统数据库来说,无论是故障宕机还是重新选主,正在执行的事务都会伴随内存信息的丢失而丢失状态。之后通过回放恢复出来的活跃事务因为无法确定状态而只能被回滚。从 Redo 日志的角度看就是回放完所有日志后仍然没有 Commit 日志。
在 OceanBase 数据库中重新选主会有一段时间允许正在执行的事务将自己的数据和事务状态写成日志并提交到多数派副本,这样在新的 Leader 上事务可以继续执行。
7 日志的控制与回收
日志文件中记录了数据库的所有修改,因此回收的前提是日志相关的数据都已经成功持久化到磁盘上。如果数据还未持久化就回收了日志,故障后数据就无法被恢复。
当前 OceanBase 数据库的日志回收策略中对用户可见的配置项有 2 个:
clog 磁盘空间使用上限,由全局配置项 log_disk_utilization_limit_threshold 控制,默认值是 95,代表允许 Clog 使用的磁盘空间占总磁盘空间的百分比。当事务日志对应的磁盘空间的使用量达到该配置项设置的值后,磁盘将停止写入,且无法再接收日志。
这是一个刚性的限制,超过此值后这个 OBServer 节点不再允许任何新事务的写入,同时不允许接收其他 OBServer 节点同步的日志。对外表现是所有访问此 OBServer 节点的读写事务报错 “transaction needs rollback”。
Clog 磁盘复用下限,由配置项 log_disk_utilization_threshold 控制。在系统工作正常时,Clog 会在此水位开始复用最老的日志文件,默认值是 Clog 独立磁盘空间的 80%,不可修改。因此,正常运行的情况下,Clog 磁盘空间占用不会超过 80%,超过则报错 “clog disk is almost full”, 提醒 DBA 处理。
8 clog disk is almost full 故障处理
对于分区数多、写入压力大的数据库集群,如果转储慢、或者租户 Unit 规格异构,那么可能导致部分副本的 Clog 回收不及时,从而导致磁盘空间使用率达到 95%,此时 observer 进程会自动停止写 Clog,从而导致这台机器上有大量副本不同步。
可以通过在服务器上执行 df -h 查看当前 Clog 盘的空间使用占比,如果 Use% 列达到了 clog_disk_usage_limit_percentage 设置的阈值,则需要进行处理。
[dave@www.cndba.cn /]# df -h
...
/dev/mapper/vglog-ob_log 196G 177G 9G 95% /observer/clog
...
从官网的描述看,这里其实就是更新太快,或者转储较慢的导致。 因为 OB 采用的是 LSM Tree,数据有基础数据(SSTable)和增量数据(MEMTable),数据在更新时写入到 redo log 之后,就认为成功了,然后等待转储和合并,当转储完成后才可以删除 redo log。
官网对这个问题说明,解决方法有 2 点:
调整参数上线从 95 到 98:
obclient> ALTER SYSTEM SET clog_disk_usage_limit_percentage=98 server=’svr_ip:2882’;
如果还没有恢复,就先移除一些redo log,这里要移除,转移到其他磁盘,第二是只能在一个 OBServer 上操作。
节点日志盘(Clog)空间满
https://www.oceanbase.com/docs/common-oceanbase-database-cn-10000000001702787
https://www.oceanbase.com/knowledge-base/oceanbase-database-20000000129
版权声明:本文为博主原创文章,未经博主允许不得转载。
- 上一篇:Oceanbase 修改参数 控制日志保留 数量
- 下一篇:达梦 DM8 DCM