输出模式
有两种输出模式
- output_mode=0: 把解码后的数据输出到CMiner自身数据库的一张表中
- output_mode=1模式:把解码后的数据输出到中间文件中
1. output_mode=0模式
在output_mode=0的模式中,解码后的数据会直接插入到表中:
- cminer_transaction: 事务信息
- cminer_content: 解码后的数据
在这个模式中,未提交的数据也会插入到cminer_content表中。如果我们每解码一条数据,就把解码位置记录到cminer_decode_position中,这样提交次数很多,性能会很差。所以我们加了参数:
- max_rows_per_commit: 解码的行数超过此配置值时,提交一次数据。
- max_bytes_per_commit: 解码后的数据字节数超过此配置值时,提交一次数据。
这样我们就大大降低了提交次数,提高了性能。
2. output_mode=1模式
在output_mode=0的模式下,数据都直接输出到了数据库中,性能较低。所以设计了 output_mode=1模式,此模式把解码后的数据直接输出到文件中,这些文件在参数out_path指定的目录中,如我们配置out_path在/home/postgres/目录下,如:
postgres=# select * from cminer_settings where key in ('out_path', 'output_mode');
key | val
-------------+------------------------
output_mode | 1
out_path | /home/postgres/outdata
(2 rows)
这时会在目录/home/postgres/outdata下生成如下的一些文件:
[postgres@cbbackup_21 ~]$ ls -l /home/postgres/outdata/
total 7544720
-rw------- 1 postgres postgres 134217582 Sep 29 16:28 cmd_00000000000000000001
-rw------- 1 postgres postgres 134217660 Sep 29 16:28 cmd_00000000000000000002
-rw------- 1 postgres postgres 134217674 Sep 29 16:28 cmd_00000000000000000003
-rw------- 1 postgres postgres 134217717 Sep 29 16:28 cmd_00000000000000000004
-rw------- 1 postgres postgres 134217705 Sep 29 16:28 cmd_00000000000000000005
-rw------- 1 postgres postgres 55509520 Sep 29 16:28 cmi_00000000000000000001
-rw------- 1 postgres postgres 55509344 Sep 29 16:28 cmi_00000000000000000002
-rw------- 1 postgres postgres 55509344 Sep 29 16:28 cmi_00000000000000000003
-rw------- 1 postgres postgres 55509432 Sep 29 16:28 cmi_00000000000000000004
-rw------- 1 postgres postgres 55508904 Sep 29 16:28 cmi_00000000000000000005
这个目录下有两类文件,一类是以“cmi”开头的文件,一类是以“cmd”开头的文件。
后面当我们启动cminer_kafka进程,cminer_kafka进程就是从这些文件中读取解码后的数据,然后把数据插入到kafka中。
当解码程序停止后,再重新开始时,通常需要从上一次的结束的位置之前很多的位置开始解码。这时因为与一样,至少要从上次的checkpoint点开始还受到长事务的影响。原因是在数据库中,每一个事务会执行多条数据,并有可能执行较长一段时间,解码程序可能会停在这个事务的中间。比如一条事务执行了三条插入:
LSN=1000: A插入: insert into test01 values(1, '111');
LSN=1100: B插入:insert into test01 values(2, '222');
LSN=1200: C插入:insert into test01 values(3, '333');
提交:
解码程序会把未提交的事务的数据都记录在内存中,只有提交事务时才把数据输出到“/home/postgres/outdata/”目录下文件中(以cmi和cmd开头的文件中)。也就是与output_mode=0模式不同,在output_mode=0模式中,未提交的数据在表cminer_content也可以看到。而在output_mode=1模式下,未提交的数据只是会缓存在内存中。
当解码到“B插入”时,程序停下来了,内存中的未完成的事务的数据如“A插入”和“B插入”会丢弃。所以我们再次启动解码程序,至少应该从“插入A”的位置(LSN=1000)开始解码才能不丢失数据。
所以在解码程序开始解码的位置,应该是最旧的事务的开始的位置的之前的checkpoint点开始解码。所以在output_mode=1模式下,并不是读到WAL日志中的一个checkpoint点马上就更新cminer_decode_position.checkpoint_lsn,而是这个checkpoint点比最旧的事务开始点更旧时才会更新。也就是cminer_decode_position.checkpoint_lsn始终是比最旧事务更旧的checkpoint点。