Oracle 1 SQL

1 Oracle 集群管理 1.2 登录数据库 sqlplus / as sysdba 2 Oracle 语法 2.1 数据类型 仅列举常见数据类型: 大类 类型 解释 数值 INT or INTGER 整数 - NUMBESR(p, s) p: 精度,整数和小数总位数,s: 小数位数 - SMALLINT 等于 NUMBESR(38) - FLOAT(p) 浮点数,p: 二进制精度,最大126 字符 CHAR(n) 固定长度字符,n: 长度,不足n用空格填充 - VARCHAR2(n) 可变长度字符,n: 最大长度,最大4000 时间 DATE 日期 - TIMESTAMP 日期和时间 二进制 CLOB 长文本数据 2.2 常用SQL 常见语法 -- 1 创建表 CREATE TABLE t1 (c1 INT, c2 VARCHAR2(10)); -- 2 插入数据 INSERT INTO t1 VALUES (1, 'abcc'); INSERT INTO t1 VALUES (2, 'ddee'); -- 3 查询数据 SELECT * FROM t1 WHERE c1 > 0; -- 4 更新数据 UPDATE t1 SET c2 = 'abbc' WHERE c1 = 1; -- 5 删除数据 DELETE FROM t1 WHERE c1 = 2; -- 6 删除表 DROP TABLE t1; 内置函数 ...

February 20, 2025 · 2 min · 222 words · Me

Vastbase

1 准备开发环境 1.1 登录远程windows 连接vpn 下载vpn软件,使用入职时他人帮忙申请的vpn账号登录 登录远程windows电脑 使用入职时他人帮忙申请的远程windows账号 登录gitlab 入职时,有人已帮忙申请gutlab账号。http://172.16.19.246 查看vastbase代码 http://172.16.19.246/VastbaseG100/src 默认无权限,可能搜不到,请找小组领导开通权限 1.2 准备vastbase编译环境 在远程windows中,登录远程centos 配置git 生成rsa密钥,配置到gitlab中 下载vastbase源码 mkdir g100 cd g100 git clone -b master git@172.16.19.246:VastbaseG100/src.git 下载vastbase依赖的二进制文件 需要自行通过svn下载,然后,上传到vastbase源码同级目录 ip: 172.16.19.4 用户名: clouder 密码: 自行询问 目录: /Database/Vastbase/third_party 配置用于编译vastbase的环境变量 cd g100 touch venv 请确保此时的目录结构如下: ls g100 |-- g100 |-- src |-- binarylibs |-- venv 设置环境变量,在venv文件中,输入以下内容: export CODE_BASE=`pwd` export BINARYLIBS=`pwd`/binarylibs # 安装目录在源码里写死了,改不了 export GAUSSHOME=`pwd`/src/mppdb_temp_install export GCC_PATH=$BINARYLIBS/buildtools/gcc7.3 export CC=$GCC_PATH/gcc/bin/gcc export CXX=$GCC_PATH/gcc/bin/g++ export LD_LIBRARY_PATH=$GAUSSHOME/lib:$GCC_PATH/gcc/lib64:$GCC_PATH/isl/lib:$GCC_PATH/mpc/lib/:$GCC_PATH/mpfr/lib/:$GCC_PATH/gmp/lib/:$LD_LIBRARY_PATH export PATH=$GAUSSHOME/bin:$GCC_PATH/gcc/bin:$PATH # 以下是vastbase增加的 export PATH=$BINARYLIBS/buildtools/cmake/bin:$PATH 配置快捷命令 ...

February 20, 2025 · 4 min · 837 words · Me

vastbase 身份认证

国策用例 4、配置客户端认证方式 hostssl all all 0.0.0.0/0 cert 1、生成国密证书 创建 CA 目录 cadir 并进入 mkdir cadir cd cadir copy 配置文件 openssl.cnf 到当前目录(不同环境,配置文件路径可能不一样) cp /etc/pki/tls/openssl.cnf . 开始搭建CA环境 mkdir ./demoCA ./demoCA/newcerts ./demoCA/private chmod 777 ./demoCA/private 创建serial文件,写入01 echo '01'>./demoCA/serial 创建文件index.txt touch ./demoCA/index.txt 修改openssl.cnf配置文件中CA_default的参数 dir = ./demoCA default_md = sha256 至此CA环境搭建完成 生成CA私钥 openssl ecparam -out demoCA/private/cakey.pem -name SM2 -genkey 生成根证书请求文件 openssl req -config openssl.cnf -key demoCA/private/cakey.pem -new -out cacert.req -subj /C=CN/ST=BJ/L=HaiDian/O=VAST/OU=SEC/CN=CLIENT 生成自签发根证书 生成根证书时,需要修改openssl.cnf文件,设置basicConstraints=CA:TRUE vi openssl.cnf 生成CA自签发根证书 openssl ca -config openssl.cnf -in cacert.req -keyfile demoCA/private/cakey.pem -selfsign -out demoCA/cacert.pem 生成服务器私钥文件server.key openssl ecparam -out server.key -name SM2 -genkey 生成服务器证书请求文件server.req openssl req -config openssl.cnf -key server.key -new -out server.req -subj /C=CN/ST=BJ/L=HaiDian/O=VAST/OU=SEC/CN=server 生成服务端/客户端证书时,修改openssl.cnf文件,设置basicConstraints=CA:FALSE vi openssl.cnf 对生成的服务器证书请求文件进行签发,签发后将生成正式的服务器证书server.crt openssl ca -config openssl.cnf -in server.req -out server.crt -days 3650 生成客户端私钥 openssl ecparam -out client.key -name SM2 -genkey 生成客户端证书请求文件 openssl req -config openssl.cnf -new -key client.key -out client.req -subj /C=CN/ST=BJ/L=HaiDian/O=VAST/OU=SEC/CN=client 对生成的客户端证书请求文件进行签发,签发后将生成正式的客户端证书client.crt openssl ca -config openssl.cnf -in client.req -out client.crt -days 3650 注:中间会产生交互,按照以下内容进行填写(需注意每个交互的common name填不一样的内容,如分别写:test1,test2,test3): Country Name (2 letter code) [AU]:CN State or Province Name (full name) [Some-State]:shanxi Locality Name (eg, city) []:xian Organization Name (eg, company) [Internet Widgits Pty Ltd]:Abc Organizational Unit Name (eg, section) []:hello --Common Name可以随意命名 Common Name (eg, YOUR name) []:world --Email可以选择性填写 Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: 1qaz!QAZ An optional company name []:world # --------------------------------------- https://gitee.com/opengauss/openGauss-server/pulls/3254 mkdir certs cp ../../tassl/tassl_demo/cert/openssl.cnf certs/ cd certs #CA openssl ecparam -genkey -name SM2 -out CA.key openssl req -config openssl.cnf -new -subj /C=CN/ST=BJ/L=HaiDian/O=YUNHEENMO/OU=MogDB/CN=FooCA -key CA.key -out CA.csr openssl x509 -sm3 -req -days 1500 -in CA.csr -extfile openssl.cnf -extensions v3_ca -signkey CA.key -out CA.crt #server openssl ecparam -genkey -name SM2 -out server.key openssl req -config openssl.cnf -new -subj /C=CN/ST=BJ/L=HaiDian/O=YUNHEENMO/OU=MogDB/CN=server -key server.key -out server.csr openssl x509 -sm3 -req -days 1500 -in server.csr -CA CA.crt -CAkey CA.key -extfile openssl.cnf -out server.crt -CAcreateserial #server_enc openssl ecparam -genkey -name SM2 -out server_enc.key openssl req -config openssl.cnf -new -subj /C=CN/ST=BJ/L=HaiDian/O=YUNHEENMO/OU=MogDB/CN=server -key server_enc.key -out server_enc.csr openssl x509 -sm3 -req -days 1500 -in server_enc.csr -CA CA.crt -CAkey CA.key -extfile openssl.cnf -out server_enc.crt -CAcreateserial #client openssl ecparam -genkey -name SM2 -out client.key openssl req -config openssl.cnf -new -subj /C=CN/ST=BJ/L=HaiDian/O=YUNHEENMO/OU=MogDB/CN=client -key client.key -out client.csr openssl x509 -sm3 -req -days 1500 -in client.csr -CA CA.crt -CAkey CA.key -extfile openssl.cnf -out client.crt -CAcreateserial #client_enc openssl ecparam -genkey -name SM2 -out client_enc.key openssl req -config openssl.cnf -new -subj /C=CN/ST=BJ/L=HaiDian/O=YUNHEENMO/OU=MogDB/CN=client -key client_enc.key -out client_enc.csr openssl x509 -sm3 -req -days 1500 -in client_enc.csr -CA CA.crt -CAkey CA.key -extfile openssl.cnf -out client_enc.crt -CAcreateserial #修改权限 chmod 0600 * #增加密码保护 openssl ec -sm4 -in server.key -out server.key -passout pass:123qweQWE gs_guc generate -S 123qweQWE -D ./ -o server openssl ec -sm4 -in server_enc.key -out server_enc.key -passout pass:234werWER gs_guc generate -S 234werWER -D ./ -o server_enc openssl ec -sm4 -in client.key -out client.key -passout pass:345ertERT gs_guc generate -S 345ertERT -D ./ -o client openssl ec -sm4 -in client_enc.key -out client_enc.key -passout pass:456rtyRTY gs_guc generate -S 456rtyRTY -D ./ -o client_enc chmod 0600 * #客户端: export CERT=`pwd` echo ' export CERT=`pwd` export PGSSLMODE=verify-ca export PGSSLTLCP=1 export PGSSLROOTCERT=$CERT/CA.crt export PGSSLKEY=$CERT/client.key export PGSSLCERT=$CERT/client.crt export PGSSLENCKEY=$CERT/client_enc.key export PGSSLENCCERT=$CERT/client_enc.crt ' > client_env source client_env #服务器: gs_guc set -D $GAUSSHOME/data -c "ssl=on" gs_guc set -D $GAUSSHOME/data -c "ssl_ciphers = 'ALL'" gs_guc set -D $GAUSSHOME/data -c "ssl_use_tlcp=on" gs_guc set -D $GAUSSHOME/data -c "ssl_ca_file = '$CERT/CA.crt'" gs_guc set -D $GAUSSHOME/data -c "ssl_key_file='$CERT/server.key'" gs_guc set -D $GAUSSHOME/data -c "ssl_cert_file='$CERT/server.crt'" gs_guc set -D $GAUSSHOME/data -c "ssl_enc_key_file='$CERT/server_enc.key'" gs_guc set -D $GAUSSHOME/data -c "ssl_enc_cert_file='$CERT/server_enc.crt'" 1、生成国密证书 # 创建 CA 目录 cadir 并进入 # copy 配置文件 openssl.cnf 到当前目录(不同环境,配置文件路径可能不一样) cp /etc/pki/tls/openssl.cnf . # 开始搭建CA环境 mkdir ./demoCA ./demoCA/newcerts ./demoCA/private chmod 777 ./demoCA/private # 创建serial文件,写入01 echo '01'>./demoCA/serial # 创建文件index.txt touch ./demoCA/index.txt # 至此CA环境搭建完成 # 生成CA私钥 openssl ecparam -out demoCA/private/cakey.pem -name SM2 -genkey # 生成根证书请求文件 openssl req -config openssl.cnf -key demoCA/private/cakey.pem -new -out cacert.req # 生成自签发根证书 # 生成根证书时,需要修改openssl.cnf文件,设置basicConstraints=CA:TRUE vi openssl.cnf # 生成CA自签发根证书 openssl ca -config openssl.cnf -in cacert.req -keyfile demoCA/private/cakey.pem -selfsign -out demoCA/cacert.pem # 生成服务器私钥文件server.key openssl ecparam -out server.key -name SM2 -genkey # 生成服务器证书请求文件server.req openssl req -config openssl.cnf -key server.key -new -out server.req # 生成服务端/客户端证书时,修改openssl.cnf文件,设置basicConstraints=CA:FALSE vi openssl.cnf # 对生成的服务器证书请求文件进行签发,签发后将生成正式的服务器证书server.crt openssl ca -config openssl.cnf -in server.req -out server.crt -days 3650 # 生成客户端私钥 openssl ecparam -out client.key -name SM2 -genkey # 生成客户端证书请求文件 openssl req -config openssl.cnf -new -key client.key -out client.req # 对生成的客户端证书请求文件进行签发,签发后将生成正式的客户端证书client.crt openssl ca -config openssl.cnf -in client.req -out client.crt -days 3650 # 注:中间会产生交互,按照以下内容进行填写(需注意每个交互的common name填不一样的内容,如分别写:test1,test2,test3): Country Name (2 letter code) [AU]:CN State or Province Name (full name) [Some-State]:shanxi Locality Name (eg, city) []:xian Organization Name (eg, company) [Internet Widgits Pty Ltd]:Abc Organizational Unit Name (eg, section) []:hello --Common Name可以随意命名 Common Name (eg, YOUR name) []:world --Email可以选择性填写 Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: 1qaz!QAZ An optional company name []:world 2、配置客户端文件 chmod 600 client.key chmod 600 client.crt chmod 600 ./demoCA/cacert.pem chmod 600 server.key chmod 600 server.crt 3、配置服务器端参数 cp server.crt server.key ./demoCA/cacert.pem $PGDATA cp client.crt client.key /home/vastbase/data/vastbase/ export PGSSLCERT="/home/vastbase/cadir/client.crt" export PGSSLKEY="/home/vastbase/cadir/client.key" export PGSSLMODE="verify-ca" export PGSSLROOTCERT="/home/vastbase/data/vastbase/cacert.pem" vi postgresql.conf ssl = on require_ssl = on ssl_cert_file = 'server.crt' ssl_key_file = 'server.key' ssl_ca_file = 'cacert.pem' ssl_crl_file = '' 4、配置客户端认证方式 vi pg_hba.conf hostssl all all 0.0.0.0/0 cert 5、重启数据库服务 vb_ctl restart vsql - vastbase -r --创建生成客户端证书时Common Name同名用户 create user test3 password'Test@123'; 1、客户端vsql连接到服务端 vsql -dvastbase -r -h IP -U test3 --预期 连接成功,提示SSL connection 1 需求背景 1.2 Oracle Profile功能 一、查看profile信息 设置sqlplus输出格式 ...

February 17, 2025 · 11 min · 2247 words · Me

vastbase 加密函数

1 需求背景 1.1 数据加密背景 加密的原理 不同场景中,适合的加密算法类型不同。对存储数据加密,通常采用对称密码算法,此处主要介绍对称密码算法: 加密原理:输入1个明文,输入1个密钥,对明文和密钥进行一些运算(比如异或,代换),可得到1个密文。密钥通常是随机生成的。 加密算法:DES算法,发布于1977年,已确定为不安全加密算法。3DES算法,调用3次DES算法,生成3个密钥,安全性与DES差别不大,也属于不安全的加密算法。AES算法,发布于2001年,通用的国际标准 数据库加密函数 几乎所有数据库,都提供内置加密函数,让用户通过SQL语句调用。最典型的场景如下: -- 假设,数据库提供函数encrypt(明文,密钥,加密算法),输出为密文 -- 用户想表't1'中存储数据'shenkun',则存储的语法如下:(用户自己保管密钥) INSERT INTO t1 VALUES (encrypt('shenkun', '一串随机的密钥', 'aes')); 1.2 oracle 加密包 早期版本的oracle中,包含1个名为dbms_obfuscation_toolkit的包,提供7个函数,主要实现加密、解密等功能: 版本信息:oracle 8i版本开始提供,oracle 10g版本开始不被推荐使用,由dbms_crypto代替,oracle 21c版本正式移除 函数列表: 生成随机数:desgetkey(seed) -> key 加密:desencrypt(input, key) -> encrypted_data 解密:descdecrypt(input, key) -> decrypted_data 生成随机数:des3getkey(which=>0, seed) -> key 加密:des3encrypt(input, key, which=>0, iv=>012345678abcdef) -> encrypted_data 解密:des3decrypt(input, key, which=>0, iv=>012345678abcdef) -> decrypted_data 哈希:md5(input) -> checksum 函数参数:函数参数有3种数据类型:varchar2, raw。与raw类型相比,如果是varchar2类型,参数名需加上_string后缀。比如,raw类型的入参名为input,则varcha2类型入参名为input_string 函数限制: desgetkey:seed长度最短为80字节 desencrypt:input长度是8字节的整数倍;key最短为8字节,超过8字节的部分被丢弃 descdecrypt:input长度是8字节的整数倍;key最短为8字节,超过8字节的部分被丢弃 des3getkey: seed长度最短为80字节 des3encrypt:input长度是8字节的整数倍;which为0时,key最短为16字节,超过16字节的部分被丢弃;which为1时,key最短为24字节,超过24字节的部分被丢弃 des3dencrypt:input长度是8字节的整数倍;which为0时,key最短为16字节,超过16字节的部分被丢弃;which为1时,key最短为24字节,超过24字节的部分被丢弃 md5:无 参考文档 函数介绍:函数背景、注意事项等:https://docs.oracle.com/cd/A97630_01/appdev.920/a96590/adgsec04.htm 函数参数:参数类型、调用示例等:https://docs.oracle.com/cd/B10500_01/appdev.920/a96612/d_obtoo2.htm 以下是上述函数的调用示例: ...

February 9, 2025 · 6 min · 1095 words · Me

Vastbase 搭建环境、编译代码、安装数据库

1 准备开发环境 1.1 登录远程windows 连接vpn 下载vpn软件,使用入职时他人帮忙申请的vpn账号登录 登录远程windows电脑 使用入职时他人帮忙申请的远程windows账号 登录gitlab 入职时,有人已帮忙申请gutlab账号。http://172.16.19.246 查看vastbase代码 http://172.16.19.246/VastbaseG100/src 默认无权限,可能搜不到,请找小组领导开通权限 1.2 准备vastbase编译环境 在远程windows中,登录远程centos 配置git 生成rsa密钥,配置到gitlab中 下载vastbase源码 mkdir g100 cd g100 git clone -b master git@172.16.19.246:VastbaseG100/src.git 下载vastbase依赖的二进制文件 需要自行通过svn下载,然后,上传到vastbase源码同级目录 在文件管理器中,输出ftp://172.16.19.4后,会提示输出账号和密码 ip: 172.16.19.4 用户名: clouder 密码: 自行询问 目录: /Database/Vastbase/third_party 配置用于编译vastbase的环境变量 cd g100 touch venv 请确保此时的目录结构如下: ls g100 |-- g100 |-- src |-- binarylibs |-- venv 设置环境变量 export CODE_BASE=`pwd` export BINARYLIBS=`pwd`/binarylibs # 安装目录在源码里写死了,改不了 export GAUSSHOME=`pwd`/src/mppdb_temp_install export GCC_PATH=$BINARYLIBS/buildtools/gcc7.3 export CC=$GCC_PATH/gcc/bin/gcc export CXX=$GCC_PATH/gcc/bin/g++ export LD_LIBRARY_PATH=$GAUSSHOME/lib:$GCC_PATH/gcc/lib64:$GCC_PATH/isl/lib:$GCC_PATH/mpc/lib/:$GCC_PATH/mpfr/lib/:$GCC_PATH/gmp/lib/:$LD_LIBRARY_PATH export PATH=$GAUSSHOME/bin:$GCC_PATH/gcc/bin:$PATH # 以下是vastbase增加的 export PATH=$BINARYLIBS/buildtools/cmake/bin:$PATH 配置快捷命令 ...

February 8, 2025 · 4 min · 850 words · Me

Oracle 安全特性

1 概述 来源:https://docs.oracle.com/en/database/oracle/oracle-database/23/dbseg 基础安全 身份认证 密码最小长度 连续失败锁定 账户锁定 新旧密码重复 密码有效期 访问控制 敏感数据发现 传输加密 安全审计 高级安全 透明加密 数据脱敏 访问控制 行级访问控制 数据库保险柜:细粒度访问控制

February 7, 2025 · 1 min · 20 words · Me

Oracle 基本介绍

1 Oracle 集群管理 1.2 登录数据库 sqlplus / as sysdba 2 Oracle 语法 2.1 数据类型 仅列举常见数据类型: 大类 类型 解释 数值 INT or INTGER 整数 - NUMBESR(p, s) p: 精度,整数和小数总位数,s: 小数位数 - SMALLINT 等于 NUMBESR(38) - FLOAT(p) 浮点数,p: 二进制精度,最大126 字符 CHAR(n) 固定长度字符,n: 长度,不足n用空格填充 - VARCHAR2(n) 可变长度字符,n: 最大长度,最大4000 时间 DATE 日期 - TIMESTAMP 日期和时间 二进制 CLOB 长文本数据 2.2 常用SQL 常见语法 -- 1 创建表 CREATE TABLE t1 (c1 INT, c2 VARCHAR2(10)); -- 2 插入数据 INSERT INTO t1 VALUES (1, 'abcc'); INSERT INTO t1 VALUES (2, 'ddee'); -- 3 查询数据 SELECT * FROM t1 WHERE c1 > 0; -- 4 更新数据 UPDATE t1 SET c2 = 'abbc' WHERE c1 = 1; -- 5 删除数据 DELETE FROM t1 WHERE c1 = 2; -- 6 删除表 DROP TABLE t1; 内置函数 ...

January 25, 2025 · 2 min · 222 words · Me

Babelfish搭建指南

Babelfish 编译环境搭建指南 适用环境:CentOS 7,离线环境,vastbase-server + sqlserver-extensions 一、创建用户 # 创建用户并设置密码 useradd vast echo "vast:gauss@123" | chpasswd # 授予 sudo 权限(加入 wheel 组) usermod -aG wheel vast # 验证 id vast 二、配置环境变量 将以下内容写入 ~/.bash_profile,每次登录自动生效: cat >> ~/.bash_profile << 'EOF' # Babelfish 基础路径 export BABELFISH_HOME=~/vastbase-server/install export BINARYLIBS=~/vastbase-server/binarylibs export GCC_PATH=$BINARYLIBS/buildtools/gcc7.3 # 编译器 export CC=$GCC_PATH/gcc/bin/gcc export CXX=$GCC_PATH/gcc/bin/g++ # cmake(优先使用项目自带版本,放在 PATH 最前面) export PATH=$BINARYLIBS/buildtools/cmake/bin:$GCC_PATH/gcc/bin:$BABELFISH_HOME/bin:$PATH # 动态库路径 export LD_LIBRARY_PATH=$GCC_PATH/gcc/lib64:$BABELFISH_HOME/lib:$BINARYLIBS/kernel/dependency/openssl/comm/lib:$LD_LIBRARY_PATH # cmake 变量(防止 Makefile 调用系统旧版本) export cmake=$(which cmake) # PG 相关 export PG_CONFIG=$BABELFISH_HOME/bin/pg_config export PG_SRC=`pwd` EOF source ~/.bash_profile 验证工具版本: ...

February 27, 2026 · 3 min · 470 words · Me

避免用户错误使用到pg插件

基本概念 这里是融合版的一个需求,属于兼容性需求类别,主要实现的是一个黑名单,是要把一个列表中的多个插件不允许在MSSQL兼容安装包中出现,或只能在5432端口(PG模式)中使用,不能在1433端口(MSSQL模式)中使用。 初步分析 根据需求列表,可以基本将需要修改的插件分为三类: 禁止在双端口安装使用; 在5432端口允许使用,1433端口禁止安装使用; 双端口都允许使用; 其中,需求描述特别提到,允许在编译阶段进行修改,由此可以对应的提出三类插件的修改方案: 在编译阶段不安装,也就是在contrib/Makefile中的SUBDIR安装插件,删除这些不允许在双端口安装的插件; 在hooks.c中增加一个名单,名单中包含这些允许在5432不允许在1433安装的插件,首先检测当前dialect是否为tsql,如果为tsql,检查是否是T_CreExtensionStmt,如果是则检查插件名单是否在这个名单之内,如果没有则放行,有则报错; 不做任何处理; 理论上,以上方案实施后,能够达到双端口不可用则直接无法找到插件,用户自行安装则不保证可能出现的任何问题;对于5432可用1433不可用,会进行报错;其他类型不做处理;应该可以达到需求描述的目的实现; 边界考虑 由于删除了某些插件编译且对某些插件在一定场景进行了屏蔽,考虑数据库升级场景,如果以前使用过此插件,现在进行了屏蔽,可能导致升级失败; 灵活性 现在的屏蔽方式是使用直接修改编译文件与硬编码名单的方式实现,如果在一个版本内,由于某些特殊原因想启用已屏蔽的插件,则在当前版本是无法实现的。如果将名单作成guc参数,则可以提供灵活性,但是一旦被手动篡改,则无法预料可能产生的问题;

February 25, 2026 · 1 min · 16 words · Me

逻辑复制

基本概念 逻辑复制是数据同步的一种方式,逻辑二字主要指的是传输数据的格式,与之相对的是物理复制。 逻辑数据格式 逻辑数据格式是指,能够由一定规则描述的,符合SQL直觉的一种数据格式,例如: [MsgType:Insert,Relation:test,New Tuple:[a, int, 100]] 从这种数据格式上,能够通过解析等方式,将数据还原为SQL语句,这也同时表现了逻辑复制的第一个特点:无视物理结构上的差异,可以在异构、跨版本的数据库之间进行数据同步。 接上例,通过一定的解析步骤,我们总能够得到: Insert into test(a) values 100::int; 对于不同内核来说,可能在语法上稍有差异,但只需要修改一些解析方式,也能够得到自身看的懂、可以运行的命令。 与物理复制的区别 逻辑复制的另外一个特点,是相对于另一种主流的数据同步方式:物理复制,来作为比较的。 几乎所有的数据库内核,在进行数据存储的时候,都是采用随机写的方式,最大化利用性能优势,将数据存储在磁盘上。那么从物理上看,一个relation的所有数据,可能并不是连续的:他们可能分布在不同的page上,由指针进行连接。那么从磁盘角度看,一个page的分布,可能是这样的: -------------- Page Header -------------- Tuple 1 for r1 -------------- Tuple 2 for r1 -------------- Tuple 1 for r2 -------------- Tuple 1 for r3 -------------- Tuple 2 for r2 -------------- 如此一来,想要在物理层面进行数据传输时,以page为单位,是无法将不同relation的tuple分开的,也就是细粒度不够。 逻辑复制的另一个特点,是可以以表为单位,进行数据同步,由一个Reader完成。 Reader逐行的去读取物理中的tuple,筛选那些符合要求的tuple,进行下一步工作。 逻辑复制提高的数据同步的细粒度,可以在库、表、甚至行上进行数据过滤,显然是一种更灵活的同步方式,在某些场景下,其效果更好,常见的有: 应用场景 某数据库使用厂商需要进行版本升级,但升级前后版本由于迭代问题,在物理存储上存在差异,导致无法进行直接替换; 某数据库使用厂商需要将原有的数据库数据迁移到一款新的数据库产品上,而这两个数据库的内核架构完全不同,物理存储存在本质差异; 某厂商部门之间使用的数据库产品不同,但部门之间存在协作,需要进行数据传递; … 架构 如图所示,逻辑复制功能,是两个实例(或生产者与消费者)之间完成的数据同步,通常我们把作为数据源端的实例,称为发布端(Publisher),而准备接收数据并进行回放的实例称为订阅端(Subscriber)。 发布端 发布端的组成部分,共分为以下几个部分:WALReader、Decoder、Sender,通常是由三个独立的线程,按照其角色完成不同的工作: WALReader:主要完成对Xlog日志的读取,即从磁盘上将当前已罗盘的Xlog record读取到内存,并发送给Decoder; Decoder:解码线程,由于WALReader发送来的数据,是物理层面的记录,Decoder会按照特定的规则,将物理信息转换为逻辑信息,从内存上看,使用一个结构体,保存Xlog record中的xid、LSN、DMLType等信息。同时,Decoder还需要将这些信息,按照约定好的协议(Protocol)将数据进行打包,其中应用最广泛的端到端协议是pgoutput(后面会介绍他的协议格式以及细节实现)。Decoder会将这些按照协议进行拼接的逻辑数据存储到私有内存中,当达到一定条件时,将数据发送给Sender线程执行发送。 Sender:将Decoder发送来的数据通过网络发送给订阅端。 发布端如何保证事务一致性 对于数据同步来说,最重要的是事务一致性,如果不能保证一致性,那么逻辑复制将是毫无意义的。而要保证事务一致性,通常主要责任在于发布端,发布端需要确保自己发送逻辑信息的顺序,是严格的,即使不能保证发送顺序一定与WAL日志写入顺序完全一致,但必须保证事务的最终一致性。为了保证事务一致性,在发布端,通常会有以下几个部分保证: 严格按照commit顺序进行事务发送:事务的提交顺序非常重要,Decoder解码到一条逻辑数据时,并不会立刻发送给Sender,而是将条变更存储起来,直到解码到该事务对应的commit,才将整个事务完发送; 错误重发:当订阅端接收到一个事务的commit时,即代表这个事务经传输完毕,订阅端会发送一个确认LSN给发布端,发布端需要确认LSN是在当前处理LSN的前面,如果此时LSN发生错乱,发布端会立即这条返回的LSN开始,重新发送这些变更; commit时间确认:在Decoder将Xlog信息解码为逻辑协议信息时对于某些类型的消息,会携带commit timestampz,这是该事务提时的瞬时时间戳; 发布端对于内存的管理 在业务系统中,有时不可避免的会出现大事务,通常包含几M甚至百M的事务变更数据,在逻辑复制模块中,上文提到,通常是将所有事务存储于内存,当遇到该事务的commit时,才进行发送。对于这种大事务来说,如果多几条,可能很容易造成内存压力,引起CPU抖动,有影响系统整体性能的可能性。 为了保证系统整体性能,当遇到这种大事务的时候,通常会设计一个内存阈值,当在内存中已经存储了多条事务变更时,一旦当前内存占用达到阈值,发布端会选择当前内存中一个最大的事务(不一定是完整的,只是transaction size最大)spill to disk;诚然,这会带来一定的IO开销,因为当我们读到被spill的事务的commit时,需要把它从磁盘上读出来,但相比于其带来的内存负荷,这是合理的取舍。 ...

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