
# 逻辑解码概述
#### 功能描述
逻辑解码为逻辑复制提供事务解码的基础能力，GaussDB可以使用SQL函数接口进行逻辑解码。此方法调用方便，不需使用工具，对接外部工具接口也比较清晰，不需要额外适配。
由于逻辑日志是以事务为单位的，在事务提交后才能输出，且逻辑解码是由用户驱动的。因此，为了防止事务开始时的Xlog被系统回收，或所需的事务信息被VACUUM回收，GaussDB新增了逻辑复制槽，用于阻塞Xlog的回收。
一个逻辑复制槽表示一个更改流，这些更改可以在其他数据库上以它们在原数据库上产生的顺序重新执行。每个逻辑复制槽都由其对应逻辑日志的获取者维护。如果处于流式解码中的逻辑复制槽所在库不存在业务，则该复制槽会依照其他库的日志位置来推进。活跃状态的LSN序逻辑复制槽在处理到活跃事务快照日志时可以根据当前日志的LSN推进复制槽；活跃状态的CSN序逻辑复制槽在处理到虚拟事务日志时可以根据当前日志的CSN推进复制槽。
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/notice_3.0-zh-cn.png)
当前版本请使用直连DN解码，分布式强一致解码（CN解码）功能默认关闭，如有需要请联系华为工程师评估后打开enable-cn-decode参数。
#### 前提条件
- 逻辑日志目前从CN或DN中抽取，如果进行逻辑复制，应使用SSL连接，因此需要保证相应节点上的GUC参数SSL设置为on。
  ![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 推荐从DN抽取逻辑日志。从CN抽取存在较多限制和短板，如需使用请联系华为工程师。
  
  - 为避免安全风险，请保证启用SSL连接。
    

- 设置GUC参数wal_level为logical。
  ![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  如果GUC参数wal_level未设置为logical，则并行解码会跳过非logical的日志段，不输出解码日志；串行解码会报错。
  
- 设置GUC参数max_replication_slots\>=每个节点所需的（物理流复制槽数+备份槽数+逻辑复制槽数）。
  ![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 每个逻辑复制槽仅解码单个数据库的解码；如需解码多个数据库，需创建多个逻辑复制槽。
  
  - 多路逻辑复制同步时，源端数据库需为每条逻辑复制链路创建独立逻辑复制槽。
  
  - 单个CN节点最多同时运行10个分布式强一致解码任务；单个DN节点最多同时运行20个解码任务。
    
- 用户需要通过DN端口连接数据库，才可以直接使用SQL函数接口进行逻辑解码操作，相关操作请参见[使用SQL函数接口进行逻辑解码](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0403.html)。如果使用CN端口连接数据库，则需要通过EXECUTE DIRECT ON (datanode_name) 'statement'语句来执行SQL函数。
- 仅限初始用户或拥有REPLICATION权限的用户进行操作。三权分立关闭时数据库管理员可进行逻辑复制操作，三权分立开启时不允许数据库管理员进行逻辑复制操作。
 
#### 注意事项
- 不支持数据页复制的DML解码。
- 逻辑复制不支持集群在线扩容。在线扩容前，需要删除已存在的逻辑复制槽，扩容完成后重新创建。
- 若因DDL反解析失败导致DDL执行失败，可通过重试重新执行。极端场景通过重试仍无法成功，可通过设置GUC参数（enable_logical_replication_ddl = OFF）关闭DDL反解析功能，优先保证业务。
- 并行解码中，decode-style值为'b'或者't'时，单条元组（插入一条元组或者更新元组中原始数据和新数据之和）大于等于1023MB的解码数据会丢弃、并打印日志信息；decode-style值为'j'时，单条元组超过500MB的解码数据会丢弃、并打印日志信息。因此，为避免数据丢失，建议单条元组大小不超过500MB。
- 在wal_level值为logical且表REPLICA IDENTITY值为FULL时，更新超过1GB的表元组会失败。
- GaussDB支持解码的数据类型为：INTEGER、BIGINT、SMALLINT、TINYINT、SERIAL、SMALLSERIAL、BIGSERIAL、FLOAT、DOUBLE PRECISION、BOOLEAN、BIT(n)、BIT VARYING(n)、DATE、DATEA、TIME\[WITHOUT TIME ZONE\]、TIMESTAMP\[WITHOUT TIME ZONE\]、CHAR(n)、VARCHAR(n)、TEXT、CLOB（解码成TEXT格式）。
- 在ORA兼容模式下，允许通过空字符串向BLOB或CLOB类型插入长度为0的字符串或NULL值。解码输出二进制格式时，可根据当前列值长度进行区分：如果为0xFFFFFFFF则表示NULL，如果为0则表示长度为0的字符串。例如，插入列值empty_blob()生成的是非NULL的空BLOB对象，解码后输出长度为0的字符串；而插入列值为''则解码输出NULL。
- 非M兼容库的浮点型数据、M兼容库的不带标度的float类型，解码结果显示精度extra_float_digits配置为3（该参数的含义参见GUC参数float_shortest_precision的具体信息）。
- 不支持对PUBLIC SCHEMA相关的DDL操作解码。
- 逻辑解码输出结果不包含会话参数设置等状态信息（如：check_function_bodies、b_format_version)，执行语句结果若依赖状态信息，在目的端回放时，需要目的端和源端的会话参数一致，否则可能报错或者数据不一致。
- 支持M-Compatibility模式数据库的DML、DDL逻辑解码，解码数据类型如下：
  - 整型：TINYINT(M)、SMALLINT(M)、MEDIUMINT(M)、BIGINT(M)、INT(M)/INTEGER、BOOL/BOOLEAN。
  
  - 浮点型：FLOAT(M,D)、DOUBLE(M,D)。
  
  - 定点型：DECIMAL(M,D)、NUMERIC(M,N)。
  
  - BIT类型：BIT。
  
  - 字符串二进制类型：CHAR(N)、VARCHAR(N)、BINARY、VARBINARY。
  
  - 文本类型：TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT。
  
  - 日期类型：DATE、TIME、DATETIME、TIMESTAMP、YEAR。
  
  - 大对象类型：TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB。
  
  - 数据类型属性：UNSIGNED、ZEROFILL。
   
- M-Compatibility模式数据库，逻辑解码特殊约束如下：
  - CREATE TABLE、ALTER TABLE、DROP TABLE等语法中的\[partition_options\]、ENGINE、ROW_FORMAT、algorithm_option、lock_option等选项在语法中无实际作用，此类语法不进行解码输出。
  
  - 对于ALTER SCHEMA、CREATE SCHEMA、DROP SCHEMA、ALTER DATABASE、CREATE DATABASE、DROP DATABASE语法中，因为M-Compatibility模式数据库下，Database与Schema等价，所以ALTER DATABASE、CREATE DATABASE、DROP DATABASE会被解码为ALTER SCHEMA、CREATE SCHEMA、DROP SCHEMA。
  
  - 对于写法不同的字符设置语法，比如CHARACTER SET、CHAR SET、CHARSET都会被解码为CHARACTER SET。
  
  - 对于ALTER TABLE tbl_name DROP {INDEX \| KEY} index_name语法，逻辑解码结果为DROP INDEX；对于删除主键 ALTER TABLE tbl_name DROP {primary key \| {index \| key} index_name} 语法会被解码为 ALTER TABLE tbl_name DROP CONSTRAINT index_name。
  
  - 对于ALTER TABLE tbl_name ADD INDEX语法，逻辑解码结果为CREATE INDEX。
  
  - 在解码DML语句时，涉及插入时间类型带精度的（time、timestamp、datetime），按照最大精度6解码。
  
  - 对于支持二进制输入的数据类型（BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB），如果数据中包括'\\0'会发生截断，仅支持并行解码BINARY格式输出（即解码任务参数decode-style='b'），串行解码、函数解码以及并行JSON、TEXT格式输出均会发生截断。
   
- REPLACE语法为DML语法，REPLACE会被解码为对数据实际的操作，比如INSERT或DELETE+INSERT（存在主键或唯一键冲突）。
- COPY语法/LOAD语法为DML语法，会被解码为对数据实际的操作，比如多条INSERT。
- 逻辑复制槽名称必须小于64个字符，使用SQL函数创建或使用复制槽时，复制槽名称仅支持小写字母、数字以及"_"、"?"、"-"、"."字符，且不支持"."或".."单独作为复制槽名称。调用JDBC API创建或使用复制槽时，复制槽名称仅支持小写字母、数字以及"_"字符（可以输入大写字母，但在内部会将其被转成小写字母进行处理，例如输入名称为MSLOT，实际名称是mslot）。
- 对多个数据库的解码需要分别在数据库内创建流复制槽并开始解码，每个数据库的解码都需要单独扫描一遍日志。
- 逻辑解码时不支持强切，强切后需要重新全量导出数据。
- 备机解码时，switchover和failover可能导致解码数据增多，需手动过滤。Quorum协议下，switchover和failover选择升主的备机需要与当前主机日志同步。
- 备机解码时若需删除数据库，需确保数据迁移完成后由主机删除对应逻辑复制槽的数据库。当前没有强制要求删除数据库之前一定要先删除库上的逻辑复制槽，可能出现当前库备机解码还未完成，主机删除数据库的情况。如果出现这种情况，当备机回放到删除数据库的动作，备机即使未完成当前库的所有解码任务，也会退出解码，如果再次重连，备机解码会因为已经删除数据库而无法启动，造成解码任务受损。
- 备机解码时，因为优先保证备机回放，存在解码线程和备机回放冲突导致函数解码和流式串行解码线程被终止的情况。如果有超大事务需要解码，则可以根据事务的解码时长适当调整相关GUC参数max_standby_streaming_delay、standby_max_query_time和standby_force_recycle_ratio。
- 只支持CN和主DN创建和删除复制槽。当删除的复制槽为最后一个复制槽时，删除完成后会产生告警"replicationSlotMinLSN is INVALID_WAL_REC_PTR!!!"和"replicationSlotMaxLSN is INVALID_WAL_REC_PTR!!!"。
- 当主机删除复制槽时，若备机Xlog回放延迟严重导致备机未能及时删除对应复制槽，后续若使用备机的复制槽进行解码，回放删除操作时将导致解码失败。使用备机复制槽解码时，建议先判断其restart_lsn是否与主机一致，若二者不一致，则该复制槽为残留复制槽。
- 不允许主备DN、多个备DN同时使用同一个复制槽解码，否则会产生数据不一致或者其他异常错误的情况。
- 数据库故障重启或逻辑复制进程重启后，解码数据可能存在重复，用户需手动过滤。
- 计算机内核故障后，解码可能存在乱码，需手动或自动过滤。
- 请确保在创建逻辑复制槽过程中未启动长事务，启动长事务会阻塞逻辑复制槽的创建。
- 主机和备机同时解码场景下，当主机发生故障、主备切换时，可能会存在某个节点超过20个复制链路上限的风险（原来主机的复制链路会转移到新主机）。
- 不支持全局临时表的DML解码。
- 不支持本地临时表的DML解码。
- SELECT INTO语句会解码创建目标表的DDL操作，不解码数据插入的DML操作。
- 为解析某个Astore表的UPDATE和DELETE语句，需为此表配置REPLICA IDENTITY属性，在此表无主键时需要配置为FULL，具体配置方式请参见《参考》中"SQL参考 \> SQL语法 \> A \> ALTER TABLE"章节中"REPLICA IDENTITY { DEFAULT \| USING INDEX index_name \| FULL \| NOTHING }"字段。
- 禁止在使用逻辑复制槽时在其他节点对该复制槽进行操作，删除复制槽的操作需在该复制槽停止解码后执行。
- 基于目标数据库可能需要源数据库的系统状态信息考虑，逻辑解码仅自动过滤模式'pg_catalog'和'pg_toast'下OID小于16384的系统表的逻辑日志。若目标数据库不需要复制其他相关系统表的内容，则逻辑日志回放过程中需要对相关系统表进行过滤。
- 在开启逻辑复制的场景下，如需创建包含系统列的主键索引，必须将该表的REPLICA IDENTITY属性设置为FULL或是使用USING INDEX指定不包含系统列的、唯一的、非局部的、不可延迟的、仅包括标记为NOT NULL列的索引。
- 在开启逻辑复制的场景下，建议用户表定义主键或唯一约束，以保证回放的确定性，否则回放SQL语句时可能会导致多行修改影响数据正确性。
- 对于缩容或升级前已存在的复制表场景，需要对复制表手动配置logical_repl_node属性或RESET为默认值，配置方式请参见《参考》中"SQL参考 \> SQL语法 \> A \> ALTER TABLE"章节中"storage_parameter"参数的使用说明，以及"logical_repl_node"属性相关说明。
- 若一个事务的子事务过多导致落盘文件过多，退出解码时需执行SQL函数pg_terminate_backend（*逻辑解码的walsender线程id*）来手动停止解码，而且退出时延增加约为1分钟/30万个子事务。因此在开启逻辑解码时，若一个事务的子事务数量达到5万，会打印一条WARNING日志。
- 在逻辑解码大事务过程中，系统会将中间解码结果写入数据盘进行暂存。事务写入的Xlog与落盘文件大小比例小于1 : 1.5，即每写入1GB大事务的Xlog日志，可能产生不超过1.5GB落盘文件，导致磁盘使用率上升，建议节点预留足够磁盘空间，确保在高峰解码期间仍满足安全水位。
- 当逻辑复制槽处于非活跃状态，且设置GUC参数enable_xlog_prune=on、enable_logicalrepl_xlog_prune=on、max_size_for_xlog_retention为非零值，且备份槽或逻辑复制槽导致保留日志段数已超过GUC参数wal_keep_segments，同时其他复制槽并未导致更多的保留日志段数时，如果max_size_for_xlog_retention大于0且当前逻辑复制槽导致保留日志的段数（每段日志大小为16MB）超过max_size_for_xlog_retention，或者max_size_for_xlog_retention小于0且磁盘使用率达到(-max_size_for_xlog_retention)/100，当前逻辑复制槽会强制失效，其restart_lsn将被设置为7FFFFFFF/FFFFFFFF。该状态的逻辑复制槽不参与阻塞日志回收或系统表历史版本的回收，但仍占用复制槽的限制数量，需要手动删除。
- 备机解码启动后，向主机发送复制槽推进指令后会占用主机上对应的逻辑复制槽（即标识为活跃状态）。在此之前主机上对应逻辑复制槽为非活跃状态，此状态下如果满足逻辑复制槽强制失效条件则会被标记为失效（即restart_lsn将被设置为7FFFFFFF/FFFFFFFF），备机将无法推进主机复制槽，且备机回放完成复制槽失效日志后当前复制槽的备机解码断开后将无法重连。
- 使用备机解码时建议只在固定备机上启动解码任务：当某个备机节点上的逻辑复制槽被强制失效时，解码任务切换到该备机节点启动时会报错。
- 在备机执行串行逻辑解码过程中，若备机回放进度滞后，可能出现解码快照获取异常并触发报错，建议备机回放完成后重试解码操作。
- 不活跃的逻辑复制槽将阻塞WAL日志回收和系统表元组历史版本清理进程，导致磁盘日志堆积和系统表扫描性能下降，因此不再使用的逻辑复制槽请及时清理。需要特别注意，在升级提交之前观察期内，使用DN扩展IP连接DN创建的逻辑复制槽，在升级回滚之前务必手动清理，否则随着DN扩展IP特性回滚无法直连DN清理。
- 分布式强一致逻辑解码（连接CN解码）仅支持GTM-Lite分布式部署及流式解码，不支持CN连接备DN进行解码、SQL逻辑解码函数、在线扩容、全局索引。
- 针对分布式强一致逻辑解码（连接CN解码）功能，CN高可用由业务负责切换。
- CN上的CSN序逻辑复制槽仅起到占位作用，不随着逻辑解码的进行而推进，同时也不会阻塞日志回收。
- 通过协议连接CN创建逻辑复制槽仅支持CSN序复制槽，通过协议连接DN创建逻辑复制槽仅支持LSN序复制槽。
- 针对分布式解码，对于故障报错或者手动停止解码客户端等场景，需等待15秒再次重试解码，如有复制槽占用则需通过执行SQL函数pg_terminate_backend（*占用该复制槽线程id*）来手动解除复制槽占用。
- 在CN上创建复制槽失败报错后，需要在CN上进行复制槽删除操作，然后在CN上重新创建复制槽。
- 在CN上删除逻辑复制槽时，若为LSN序逻辑复制槽，则仅删除当前节点复制槽，其他节点同名复制槽不受影响；否则只要其他节点有残留同名CSN序逻辑复制槽，执行删除时不会因为某些节点不存在复制槽而报错，同时所有节点的同名复制槽会被成功删除；如果任何节点均不存在该复制槽，则报错。
- 在CN上创建CSN序逻辑复制槽时，某些节点如残留同名LSN序逻辑复制槽，需在这些节点执行删除残留复制槽的操作。否则会在除当前CN节点外，其他不存在同名复制槽的CN和主DN节点上创建CSN序逻辑复制槽。
- 如果当前CN节点残留LSN序逻辑复制槽，同时其他某些节点上残留同名CSN序逻辑复制槽，则在当前CN节点上执行删除复制槽操作仅会删除本地LSN序逻辑复制槽，待删除完成后再次执行删除操作方可删除其他节点的同名复制槽。
- 解码使用JSON格式输出时不支持数据列包含特殊字符（如'\\0'空字符），解码输出列内容将出现被截断现象。
- 不支持无日志表的DML解码。
- 执行备份恢复操作时，实例恢复完成后会清理所有的逻辑复制槽，如有需要须重新建槽。执行备份恢复操作时，需要停止所有解码任务，否则有可能导致逻辑复制槽清理失败。
- 集群库级恢复操作后，该数据库数据字典复制槽无法正常使用，需要重新执行实例级逻辑解码数据字典基线化操作（会导致实例上其他数据库的数据字典复制槽失效，需要重建数据字典类型复制槽），执行基线化前请确认评估其他数据库数据字典槽失效风险。
- 删除复制槽需要在删除数据库之前执行，当逻辑复制槽所在数据库被删除后，这些复制槽变为不可用状态，需要用户手动删除，否则会阻塞wal日志回收。
- 当同一事务产生大量需要落盘的子事务时，同时打开的文件句柄可能会超限，需将GUC参数max_files_per_process配置成大于子事务数量上限的两倍。
- 不支持全局二级索引，不支持分布列修改的DML解码。
- 容灾集群的备集群不支持通过SQL系统函数或工具进行逻辑解码。
- 不支持账本数据库功能，当前版本如果开启解码任务的数据库中有关于账本数据库的DML操作，则解码结果中会包含hash列，从而导致回放失败。
- 扩容场景下，若集群中创建有逻辑复制槽，会导致扩容失败，因此扩容前需要删除当前集群中已存在的逻辑复制槽。
- 不支持主键、外键、唯一约束中的信息约束（如not enforced等）选项，如果出现信息约束，则涉及信息约束的约束不解码，其他DDL照常解码。例如："CREATE TABLE test(a int primary key not enforced);"语句会被解码为"CREATE TABLE test(a int);"。
- 使用CREATE TABLE语法创建表时不支持MURMURHASH选项的解码，若有MURMURHASH选项，该DDL语句将不解码。
- 仅支持wal_level=logical的WAL日志解码，对于非logical的日志，串行解码（包括函数解码）输出结果中没有对应的值和类型，并行解码不输出其逻辑日志。
- 逻辑解码支持的DML类型在Xlog中有如下几种操作：
  - Astore：INSERT、DELETE、UPDATE、MULTI-INSERT。
  
  - Ustore：INSERT、DELETE、UPDATE、MULTI-INSERT。
   
- wal_level值为logical的情况下，Xlog日志数据量相比hot_standby级别有一定膨胀。例如：在TPCC场景下，Astore的Xlog膨胀率约为11%，Ustore的Xlog膨胀率约为110%。
- 在大小写不敏感数据库中进行解码时，无论创建表名或用户名时使用的是大写还是小写，解码选项白名单（white-table-list）或黑名单（exclude-users）中的表名或用户名都须使用小写。
- 函数解码不支持0x字符。
- 在直连DN解码场景中，在解码到还未提交的事务时需等待当前事务提交确认：若等待时长超过transaction_sync_timeout参数值，会因超时而导致解码中断。
- 关于指定策略号的ILM压缩语法，由于高级压缩的特性机制，源端和目标端实例上表的策略号可能会不一致。
  ```
  gaussdb=# ALTER TABLE tbl_ilm ILM ENABLE POLICY p1; --p1为源库的策略号
  gaussdb=# ALTER TABLE tbl_ilm ILM DISABLE POLICY p1; --p1为源库的策略号
  gaussdb=# ALTER TABLE tbl_ilm ILM DELETE POLICY p1; --p1为源库的策略号
  ```
  
- 逻辑复制槽会保护未解析Xlog对应版本的系统表记录不被过早清理。当业务中包含大量的DDL操作，且逻辑复制槽处于不活跃状态或者客户端消费过慢时，会导致系统表历史版本过多。由于GaussDB数据页面管理的约束（同一页面中无法存放xid差值超过2\^32的两条记录），当系统表历史版本过多时，可能会阻塞DDL和DML等业务操作无法正常执行（错误码：GAUSS-21297）。
  处理措施：
  - 及时清理不再使用的逻辑复制槽。
  
  - 如果逻辑复制槽推进过慢，请联系技术支持进行处理。
    
- 并行逻辑解码任务会占用部分CPU资源，如果解码并行数过多，可能会引发资源争抢，影响在线业务。在x86架构部署中，硬件配置规格为128核CPU/1024GB内存，TPCC场景下，每个并行解码任务（并行度为4）对在线业务影响约15%。
- 如果系统资源不足或运行环境波动，可能出现解码线程创建失败或启动超时，进而导致并行逻辑解码任务启动失败，对应报错：Wait for worker ready failed。偶发问题可通过客户端重试逻辑解码临时规避，如果故障频繁复现，需降低集群整体负载，保障解码任务具备充足资源正常运行。
- 若表名、列名、索引名等数据库对象名属于系统关键字（如FLOAT、ENTITYESCAPING等），解码结果无法保证这类关键字能被反引号\`或双引号"正确包裹转义。因此在目标库应用解码结果时，需遵循目标库的语法规范，按需为关键字补充或修改\`或"包裹，避免出现语法解析报错。
- 当表的分布方式为非Replication类型时，DN解码只解析当前节点的WAL日志。
 
#### SQL函数解码性能
1. 在Benchmarksql-5.0的100warehouse场景下，采用pg_logical_slot_get_changes时：
   - 单次解码数据量4K行（对应约5MB～10MB日志），解码性能0.3MB/s～0.5MB/s。
   
   - 单次解码数据量32K行（对应约40MB～80MB日志），解码性能3MB/s～5MB/s。
   
   - 单次解码数据量256K行（对应约320MB～640MB日志），解码性能3MB/s～5MB/s。
   
   - 单次解码数据量再增大，解码性能无明显提升。
   
   
   如果采用pg_logical_slot_peek_changes + pg_replication_slot_advance方式，解码性能相比采用pg_logical_slot_get_changes时要下降30%～50%。
   
2. 在Benchmarksql-5.0的100warehouse场景下，采用pg_logical_get_area_changes时：
   - 单次解码数据量4K行（对应约5MB～10MB日志），解码性能0.3MB/s～0.5MB/s。
   
   - 单次解码数据量32K行（对应约40MB～80MB日志），解码性能3MB/s～5MB/s。
   
   - 单次解码数据量256K行（对应约320MB～640MB日志），解码性能3MB/s～5MB/s。
   
   - 单次解码数据量再增大，解码性能无明显提升。
    
3. 在Benchmarksql-5.0的100warehouse场景下，采用pg_logical_slot_get_binary_changes时：
   - 单次解码数据量4K行（对应约5MB～10MB日志），解码性能0.3MB/s～0.5MB/s。
   
   - 单次解码数据量32K行（对应约40MB～80MB日志），解码性能2MB/s～3MB/s。
   
   - 单次解码数据量256K行（对应约320MB～640MB日志），解码性能2MB/s～3MB/s。
   
   - 单次解码数据量再增大，解码性能无明显提升。
   
   
   如果采用pg_logical_slot_peek_binary_changes + pg_replication_slot_advance方式，解码性能相比采用pg_logical_slot_get_binary_changes时要下降30%～50%。
   
 
#### 流式解码性能
在并行解码的标准场景下（16核CPU、内存128GB、网络带宽 \> 200MBps、表的列数为10\~100、单行数据量0.1KB\~1KB、DML操作以insert为主、不涉及落盘事务即单个事务中语句数量小于4096、parallel-decode-num为8、解码格式为't'且开启批量发送功能），连接DN解码性能（以Xlog消耗量为标准）不低于100MBps，连接CN解码性能不低于80MBps。为保证解码性能达标以及尽量降低对业务的影响，一台备机上应尽量仅建立一个并行解码连接，保证CPU、内存、带宽资源充足。
