海量 透明加密 设计

1 透明加密 1.1 功能简述 关于透明加密的基本概念,请看需求文档。 用户使用透明加密的示例如下: CREATE TABLE t1 (c1 TEXT, c2 TEXT); CREATE ENCRYPTION KEY tde_key WITH (source=local, password='pass.123'); CREATE ENCRYPTION POLICY ep1 FRO t1 KEY tde_key; INSERT INTO t1 VALUES ('data1', 'data2'); INSERT INTO t1 VALUES ('data1', 'data2'); SELECT * FROM t1; 1.2 实现方案 1.2.1 整体架构 透明加密的核心目标,是通过数据加密方案,解决攻击者绕过数据库安全机制,直接从磁盘窃取数据的问题。 在加密数据后,需要确保不影响内核在数据上进行计算。因此,需要在存储层底层,对数据进行加密。另外,为确保存储底层能够识别哪些数据加密,哪些数据不加密,以及使用什么算法加密等,上层需传递加密信息。透明加密逻辑架构如下: 1.2.2 工作流程 为适配存储底层设计,同时兼顾加密性能,以Page为粒度进行加密,并且,在Page中,存储加密信息。 1.2.3 详细流程 一、启动进程 在启动进程阶段,故障恢复时,如果回放到属于加密表的xlog,涉及到解密Page,因此,需在故障恢复前加载密钥。 main # 1. 启动数据库进程(基于pg-16代码) PostmasterMain # 2. 启动postmaster进程 SelectConfigFiles # 3. 读取GUC文件 'tde_load_encryption_key' # 4. 读取密钥文件(后文介绍密钥如何生成) SysLogger_Start StartupDataBase # 5. 开始故障恢复 StartupProcessMain StartupXLOG ReadControlFile PerformWalRecovery for loop: ReadRecord # 6. 读取xlog ApplyWalRecord # 7. 重放xlog GetRmgr.rm_redo ... heap_xlog_insert XLogReadBufferForRedo XLogReadBufferForRedoExtended XLogReadBufferExtended ReadBufferWithoutRelcache ReadBuffer_common smgrread # 8. 读取数据文件 # 需解密,后文统一介绍 ServerLoop for loop: ConnCreate BackendStartup BackendRun PostgresMain # 9. 启动postgres进程 StartCheckpointer StartBackgroundWriter StartChildProcess AuxiliaryProcessMain BackgroundWriterMain # 10. 启动bgwriter进程 二、生成密钥 当前版本,所有表,使用同一个数据密钥。因此,暂时无需新增系统表,存储密钥对象。 ...

March 23, 2026 · 3 min · 545 words · Me

海量 mac 设计

1 强制访问控制 1.1 功能简述 从实现的角度看,当用户执行SQL时,强制访问控制主要实现以下功能: CREATE ACCESS POLICY ..:在系统表中,记录ACCESS POLICY,以及其中的LABLE等信息 CREATE TABLE ..:创建表时,如果设置acess_policy字段,则自动为表新增1列隐藏列,列名为access_label INSERT ..:向表插入数据时,根据当前用户的write_label,自动为数据生成access_label列的值。 SELECT ..:从表查询数据时,根据当前用户的read_label,自动为查询语句添加过滤条件has_mac_permission(access_label, read_label) 另外,如果为表设置访问策略,需在索引中同时设置访问策略: CREATE INDEX ..:自动为索引新增1列,列名为access_label 对于一些其他语法,也许单独适配,包括: COPY ..:自动修改旧数据的access_label值 1.2 实现方案 1.2.1 整体流程 本文重点从源码角度,介绍强制访问控制策略如何基于隐藏列,实现强制访问控制,包括:创建、填充、匹配隐藏列等流程。 核心功能的大致流程如下: User Vastbase Disk +---------------------------------------------------+---------------------------------------------------------+ # 管理员 | 1. CREATE ACCESS POLICY .. LEVEL .. LABEL .. --> | | 2. 存储access policy至系统表vb_access_policy --> | 3. 存储access level至系统表vb_access_level --> | 4. 存储access label至系统表vb_access_label --> | 5. CREATE TABLE .. (access_policy=..) --> | | 6. 识别是否设置access_policy | 7. 自动添加隐藏列access_label | 8. 存储access_policy至系统表pg_class --> | 9. 存储accessl_label定义至系统表pg_attribute --> | 10. CREATE USER .. ACCESS POLICY .. READ LABEL .. WRITE LABEL --> | | 11. 存储access_policy, read_label, write_label至系统表pg_authid --> # 普通用户 | 12. vsql -U username -W password --> | | 14. set read_label = .. / write_label = .. --> | | 15. 查询pg_authid,判断read_label/write_label是否合法 <-- | 16. 设置临时的read_label/write_label | 17. 如何用户未自动设置read_label/write_label,自动根据pgauthid设置 | 18. INSERT .. --> | | 19. 查询pg_class,判断表是否有access_policy <-- | 20. 自动为隐藏列赋值,取值为write_label | 21. SELECT .. --> | | 22. 查询pg_class,判断表是否有access_policy <-- | 23. 语义分析 | 24. 查询重写:自动新增过滤条件:WHERE has_mac_permission(access_label, read_label) | 24. 计划执行:扫描Tuple,根据过滤条件,过滤不满足权限检查的Tuple 1.2.2 详细流程 一、创建策略 当用户创建策略时,例如: ...

March 23, 2026 · 4 min · 759 words · Me

海量 15 设计 逻辑复制性能优化

1 逻辑复制性能优化 1.1 功能简述 原理: 假设,发布端执行INSERT INTO t1 VALUES(1,'data1'),更改1行数据,产生1条wal日志。逻辑复制功能将读取这条wal,解码并生成1条message,将message发送至订阅端。订阅端应用这条message,等价于重新执行INSERT INTO t1 VALUES(1,'data1')。 问题: 308.1 psu1以及之前版本,逻辑复制性能较低。以tpcc场景为例,40w tmpc时,发布端产生wal日志速度约100m/s,订阅端的复制速度约10+m/s。 客户: 滚动升级场景中,备机停机升级,主机持续执行业务,备机升级后使用逻辑复制追赶主机数据。长存客户场景,主机产生wal日志速度约40-50m/s,旧版本逻辑复制速度10+m/s,由于逻辑复制速度太慢,备机无法追赶主机,最终导致升级失败。 优化 本需求设计与实现并行逻辑复制机制,大幅提高逻辑复制速度,在上述场景中,订阅端速度可达到70-90m/s。并行逻辑复制分为3个关键子机制: 发布端多线程并行解码 发布端与订阅端流复制传输协议 订阅端多线程并行应用 1.2 实现方案 本章分3个章节,分别介绍3个关键子机制。 1.2.1 发布端并行解码机制 在旧版本中,发布端采用串行解码机制,只有1个walsender线程,串行执行:1次读取1条wal日志,解码1条wal生成1条message,缓存或发送message。 旧版本代码中,发布端有实现并行解码的代码,但是,无法直接使用,订阅端只能是工具,不能是数据库实例,且存在大量问题。本需求基于旧版本并行解码,实现权限的并行解码机制。 并行解码机制,将启动多个线程,包括1个reader、多个decoder、1个walsender,它们的功能如下: reader:1次读取1条wal日志,将wal发送给decoder decoder:1次接收1条reader发送的wal,解码生成message,将message发送给walsender walsender:1次接收1条decoder发送的message,将message发送给订阅端 线程架构图如下: lsn 1-10 d1 1 4 collect 阻塞 1 d2 2 5 2 d3 3 6 3 1.2.2 发布端与订阅端流复制协议 一、握手阶段 订阅端与发布端建立连接时,订阅端会根据CRETE SUBSCRIPTION语法设置的参数,生成连接命令,根据连接命令,发布端和订阅端决定采用哪种通信协议,究竟是采用事务复制协议(旧版本)还是流复制协议(新版本)。 事务复制协议(旧版本) 订阅端发送的连接命令如下: START_REPLICATION SLOT "$slot_name" LOGICAL $start_lsn (proto_version '3', publication_names '"$publication_name"') 流复制协议(新版本) 如果CRETE SUBSCRIPTION时,指定worker_number>1,即启用并行逻辑复制机制,将使用新的连接命令,订阅端发送的连接命令如下: START_REPLICATION SLOT "$slot_name" LOGICAL $start_lsn (proto_version '3', publication_names '"$publication_name"', streaming 'extreme', parallel-decode-num '20', max-recordbuffer-in-memory '100', max-txn-in-memory '100') 上述命令中新增了多个参数: ...

May 6, 2026 · 6 min · 1200 words · Me
心情不好的时候可以点一下 🐱
×
🤖 Doubao AI ×
Hi! 我是你的技术助手。关于代码、架构或 Bug,随时问我!🚀