LightDB支持从节点转发DML

发布时间 2023-07-06 09:58:46作者: Gao科技

LightDB, 是一个Enterprise Postgres, 恒生电子生产.

它在22.1(2022Q1)版引入一个实验性功能, standby(从节点)可接受写数据请求, 转发给主节点处理; 如果是只读请求, 在standby执行.

在ligitdb.conf的shared_preload_libraries选项后面添加lt_standby_forward以加载插件, 如:

shared_preload_libraries='lt_stat_statements,lt_stat_activity,lt_prewarm,lt_cron,lt_hint_plan,lt_show_plans,lt_standby_forward'

使用lt_standby_forward.enable_forward控制, session级别, 默认off. 可以写在lightdb.conf中, db实例级别生效.

lt_standby_forward.enable_forward = on

启用后, 如下图, client连standby, 如果发送insert等'写SQL', standby会通过conn2转发给primary.

flowchart client--conn1-->standby--conn2-->primary

当客户端使用用户user1连接standby上的db1时, 上图conn2的连接参数看起来像下面这样(不需要配置, 举例说明原理):

primary_conninfo dbname=db1 user=user1 application_name=lt_standby_forward options='-c opt1=value1 -c opt2=value2'

使用示例:

-- 连standby
$ ltsql -p 18989 -U lightdb
ltsql (13.8-22.3)

lightdb@lt_test=> 
lightdb@lt_test=> select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)

lightdb@lt_test=> create table t1(id int); --已加载库, 未启用
ERROR:  cannot execute CREATE TABLE in a read-only transaction
lightdb@lt_test=> set lt_standby_forward.enable_forward = on; --启用转发功能
SET
lightdb@lt_test=> create table t1(id int);
CREATE TABLE
lightdb@lt_test=> insert into t1 values(1),(2);
INSERT 0 2
lightdb@lt_test=> select * from t1;
 id 
----
  1
  2
(2 rows)

lightdb@lt_test=> select pg_is_in_recovery(); --上面是t(true), 现在是f(false), 说明这条语句被转发了
 pg_is_in_recovery 
-------------------
 f
(1 row)

lightdb@lt_test=> select pid,application_name from pg_stat_replication; -- standby上查不到replication
 pid | application_name 
-----+------------------
(0 rows)

上面的连接(ltsql)不要关闭, 新开一个连接连primary

--连primary
$ ltsql -p 8989 -U lightdb
ltsql (13.8-22.3)

lightdb@lt_test=> select pid,application_name from pg_stat_replication; -- primary上可以查到replication
  pid  | application_name 
-------+------------------
 12556 | walreceiver

 lightdb@lt_test=> select datname,usename,application_name,client_addr from pg_stat_activity where application_name like '%standby%'; -- primary上可以查到conn2, 前提是前面连standby不要断开
 datname | usename |  application_name  | client_addr 
---------+---------+--------------------+-------------
 lt_test | lightdb | lt_standby_forward | 127.0.0.1
(1 row)

根据文档, 有一些限制:

  1. 转发delete, update, update, insert, select with modifying CTE
  2. 转发调用会修改数据 (volatile) 的函数的select/call
  3. 只读事务在standby执行, 否则转发到primary
  4. 事务中不能含有DDL
  5. 视图会在standby展开,转发给primary. 如果视图中有当前用户无权限访问的对象, 则查询失败
  6. set命令会在standby和primary上都执行; show命令在standby执行; 不支持在连接建立后set xxx_timeout参数; timeout参数在ltsql/jdbc连接串中指定
  7. 不支持COPY FROM
  8. 不支持create temp/unlogged table
  9. 上面未提及的命令会转发到primary

(LightDB, 转发DML, DML转发, forward)