• [技术干货] 【集合贴】华为云关系数据库汇总
    华为云目前主推的数据库大致分三类:自研“云原生”架构:TaurusDB、GaussDB 系列;传统托管式 RDS:RDS for MySQL / PostgreSQL / SQL Server / MariaDB;轻量级 Flexus 版 RDS。下面把你能看到的 7 个名字一次性讲清差异、适用场景和选型建议。一、TaurusDB(云原生 MySQL 兼容版)定位华为云 2019 年自研的“云原生”OLTP 数据库,100% MySQL 8.0 协议兼容,但存储引擎、复制机制全部重写。核心差异点存算分离:计算节点共享同一份分布式存储,无需 binlog 同步。扩展性:最多 15 个只读节点,加节点分钟级完成,与数据量无关;存储 128 TB 内自动扩容。性能:官方数据百万级 QPS,复杂查询可“下推”到存储层,TP 场景 7× 于原生 MySQL。可用性:RTO<10 s;备份基于快照+redo,秒级完成。只支持 MySQL 8.0。一句话总结业务量上涨快、读写比例高、需要秒级加只读、不想做分库分表,选 TaurusDB。二、GaussDB(for MySQL / 主备版 / 分布式版)定位华为自研企业级数据库家族,分三条子产品线:GaussDB(for MySQL)外观与 TaurusDB 几乎一样(也是存算分离、MySQL 协议),但面向政府/央国企、要过等保/信创验收,内核增加全密态、国密算法、可信执行环境。GaussDB 主备版(原 GaussDB 100)自研 SQL 引擎,语法同时兼容 Oracle/MySQL/PostgreSQL 三种模式,单节点性能高,适合 Oracle 替换。GaussDB 分布式版(原 GaussDB 200)Share-Nothing MPP,PB 级分析+事务混合,用于大型 ERP、计费、数据仓库。一句话总结要信创、国密、Oracle 替换、PB 级混合负载,选 GaussDB 系列;如果只是互联网高并发,TaurusDB 更轻量。三、RDS for MySQL / PostgreSQL / SQL Server / MariaDB定位经典托管 RDS:在虚拟机里帮你装数据库、做主备、备份、补丁、监控,你拿到的是 100% 原生引擎。共同特点版本丰富:MySQL 5.6/5.7/8.0,PostgreSQL 11-15,SQL Server 2017/2019/2022,MariaDB 10.5。扩展方式:主备+最多 5 只读;加只读需要复制全量数据,时间与数据量成正比。存储上限:4 TB(部分地域 8 TB)。复制机制:主备 binlog/wal 同步,RTO≈30 s。功能完整:白名单、参数组、只读实例、代理、读写分离、备份恢复到任意一秒。差异速览MySQL:生态最大,通用 OLTP。PostgreSQL:复杂查询、JSON、GIS、时序扩展强。SQL Server:自带商业特性(SSRS、SSIS、T-SQL)、Windows 身份认证。MariaDB:比 MySQL 更激进的开源特性,部分老系统指定版本迁移用。一句话总结数据量 <4 TB、团队熟悉原生引擎、需要某个特定小版本或 Windows 生态,直接选对应 RDS。四、Flexus 云数据库 RDS定位“轻量级、低成本”子品牌,底层与 RDS for MySQL 同源,但:起步规格 1C2G,价格最低到 0.08 元/小时;控制台极简,缺省只开主节点(高备可后开);最大 1 TB 存储,性能上限 1 万 QPS 左右;适合个人博客、小程序、开发测试、毕业设计。一句话总结预算敏感、非核心系统、需要“能用就行”,选 FlexusRDS;生产业务还是回 RDS/TaurusDB。五、一张表看完所有区别维度TaurusDBGaussDB(for MySQL)RDS for MySQL/PostgreSQL/SQL Server/MariaDBFlexusRDS架构云原生存算分离同左+国密/可信传统主备精简主备引擎自研(兼容MySQL8.0)自研(兼容MySQL8.0)原生引擎原生MySQL只读节点≤15,分钟级≤15,分钟级≤5,与数据量相关≤1存储上限128 TB128 TB4/8 TB1 TB典型RTO<10 s<10 s<30 s<30 s是否信创否是否否起步价格中等高中极低适用场景高并发、快速扩容政企、Oracle替换、安全合规通用、版本特定开发测试、轻量级六、选型速决流程要信创/Oracle 语法兼容/国密 → GaussDB 系列互联网业务、读写突增、加节点要秒级、MySQL8.0 即可 → TaurusDB只要原生 MySQL/PostgreSQL/SQL Server/MariaDB,数据量 <4 TB → 对应 RDS个人/小程序/测试,预算压到最低 → FlexusRDS这样就不会再被一堆名字绕晕,按业务规模、合规、预算三步就能敲定。祝选型顺利!
  • [技术干货] 数据库死锁:高并发场景下的“幽灵”,常见场景解决办法-转载
    数据库死锁是高并发场景下的“幽灵问题”——它往往突然发生,导致业务中断,且排查起来需要结合数据库原理、日志分析和场景还原。以下内容从基础原理→诊断方法→应急解决→长效预防展开,覆盖主流数据库(SQL Server/MySQL/Oracle),帮你系统掌握死锁的应对之道。 一、先搞懂:死锁的本质与必要条件死锁是指两个或多个事务互相持有对方需要的锁,且都不愿释放,导致所有事务无限等待的状态。其发生的四个必要条件(缺一不可):互斥:资源(如行、页、表)一次只能被一个事务占用;请求与保持:事务已持有某个资源,又请求新的资源(且不释放已有资源);不可剥夺:资源不能被强制从持有事务中夺走;循环等待:事务间形成“事务A等事务B的资源,事务B等事务A的资源”的闭环。二、死锁的诊断:如何快速定位问题?诊断死锁的核心是还原“死锁环”——即找出哪些事务、访问了哪些资源、持有哪些锁、等待哪些锁。以下是各数据库的常用诊断工具和方法:1. 通用诊断步骤不管用什么数据库,诊断死锁的流程基本一致:Step 1:捕获死锁事件:开启数据库的死锁日志记录(如SQL Server的Trace Flag 1222、MySQL的innodb_print_all_deadlocks);Step 2:收集现场证据:获取死锁时的锁信息、事务历史、SQL语句;Step 3:分析死锁环:通过工具还原事务的锁请求顺序,找到循环等待的源头。2. 主流数据库的具体诊断方法(1)SQL ServerSQL Server提供了丰富的DMV(动态管理视图)和工具来诊断死锁:① 查看死锁错误日志:SQL Server的1205错误(死锁牺牲品)会记录死锁详情,可通过ERRORLOG或sys.dm_os_ring_buffers查询:-- 查询最近的死锁信息SELECT * FROM sys.dm_os_ring_buffers WHERE ring_buffer_type = 'RING_BUFFER_DEADLOCK_CHAIN';② 用DMV还原死锁环:结合sys.dm_tran_locks(锁信息)、sys.dm_os_waiting_tasks(等待任务)、sys.dm_exec_requests(执行请求)分析:-- 查找当前死锁的事务和锁SELECT     tl.request_session_id AS spid,    tl.resource_type,    tl.resource_associated_entity_id,    tl.request_mode,    tl.request_status,    er.blocking_session_id,    er.command,    sqltext.text AS sql_statementFROM sys.dm_tran_locks tlINNER JOIN sys.dm_os_waiting_tasks w ON tl.lock_owner_address = w.resource_addressINNER JOIN sys.dm_exec_requests er ON w.session_id = er.session_idCROSS APPLY sys.dm_exec_sql_text(er.sql_handle) sqltext③ 工具辅助:Extended Events:捕获xml_deadlock_report事件,生成死锁的XML报告(可视化死锁环);SQL Profiler:跟踪死锁事件(需谨慎,性能开销大)。(2)MySQL(InnoDB)MySQL的InnoDB引擎通过SHOW ENGINE INNODB STATUS命令查看死锁信息:① 开启死锁日志:在my.cnf中设置innodb_print_all_deadlocks = ON,死锁信息会写入错误日志;② 查看死锁详情:执行SHOW ENGINE INNODB STATUS;,切换到LATEST DETECTED DEADLOCK section,会显示:死锁的两个事务的SQL语句;每个事务持有的锁(如行锁、间隙锁);等待的锁资源。(3)OracleOracle通过AWR报告或ASH分析定位死锁:① 查看死锁日志:查询V$LOCK和V$SESSION视图:-- 查找死锁的会话SELECT s.sid, s.serial#, s.username, l.type, l.id1, l.id2FROM v$lock lINNER JOIN v$session s ON l.sid = s.sidWHERE l.block = 1; -- 阻塞其他会话的锁② 生成死锁跟踪文件:设置EVENT 10046 TRACE NAME CONTEXT FOREVER, LEVEL 12,生成包含死锁详情的跟踪文件(需用TKPROF解析)。三、死锁的应急解决:先止损,再排查一旦发生死锁,需快速恢复业务,再分析根源:1. 紧急处理方法① 终止牺牲品事务:数据库会自动选择一个事务作为“牺牲品”(返回1205/1213错误),但有时需手动终止阻塞事务:SQL Server:KILL <SPID>;MySQL:KILL <CONNECTION_ID>;Oracle:ALTER SYSTEM KILL SESSION '<SID>,<SERIAL#>'。② 回滚长事务:如果某个长事务持有大量锁,主动回滚它可以快速释放资源。2. 避免“二次死锁”不要盲目重启数据库:重启会清除锁信息,但可能丢失现场;检查应用程序的重试逻辑:死锁后应用程序应指数退避重试(如等待1秒→2秒→4秒,最多3次),避免立即重试加重负载。四、死锁的长效预防:从设计到运维的闭环预防死锁的核心是破坏死锁的四个必要条件,以下是具体措施:1. 设计阶段:从源头减少死锁可能① 减少事务粒度:将大事务拆分为小事务(如批量更新拆成逐条或分批次),缩短锁的持有时间。例如:❌ 坏实践:UPDATE table SET col=1 WHERE id IN (1..10000);(持有大量锁);✅ 好实践:循环更新100条/批,每批提交一次。② 统一资源访问顺序:所有事务都按相同的顺序访问表或行(如先访问表A再访问表B,不要有的事务先A后B,有的先B后A)。例如:事务1:更新表X→更新表Y;事务2:必须也更新表X→更新表Y(避免循环等待)。③ 避免长事务:不要在事务中做无关操作(如查询大量数据、调用外部API、等待用户输入),这些操作会延长锁的持有时间。 2. 技术手段:用数据库特性降低死锁概率① 选择合适的隔离级别:高隔离级别(如SQL Server的Serializable、MySQL的Repeatable Read)会增加锁的竞争,尽量使用读已提交快照隔离(RCSI)或乐观并发:SQL Server:开启READ_COMMITTED_SNAPSHOT,事务读取时用行版本控制,不持有共享锁;MySQL:使用READ COMMITTED隔离级别(减少间隙锁);Oracle:默认的READ COMMITTED+行版本控制(Undo表空间)。② 使用乐观锁:用版本号或时间戳代替悲观锁,避免长时间持有排他锁。例如:表结构增加version字段,更新时检查版本:UPDATE table SET col=1, version=version+1 WHERE id=123 AND version=old_version;AI写代码sql123如果更新失败(版本号变了),说明数据已被修改,应用程序重试即可。③ 优化索引:缺少索引会导致全表扫描,获取更多锁(如更新一个无索引的列,会锁整行甚至整表)。确保:WHERE条件中的列有索引;连接条件中的列有索引;避免索引失效(如函数转换、类型隐式转换)。3. 运维层面:监控与预警① 实时监控锁等待:用Prometheus+Grafana或数据库自带工具监控锁指标:SQL Server:sys.dm_os_waiting_tasks(等待任务数)、sys.dm_tran_locks(锁持有数);MySQL:SHOW GLOBAL STATUS LIKE 'Innodb_row_lock%'(行锁等待数、超时数);Oracle:V$LOCK(锁数量)、V$SESSION_WAIT(等待事件)。② 设置死锁告警:当死锁次数超过阈值(如1分钟1次)时,触发邮件/钉钉告警,及时排查。4. 测试阶段:模拟高并发场景用JMeter/LoadRunner模拟高并发请求,提前暴露死锁问题;对核心业务流程做压力测试,验证锁竞争情况。五、常见死锁场景与解决方法以下是高频死锁场景及针对性解决方案: 1. 交叉更新死锁场景:事务1更新行A→更新行B;事务2更新行B→更新行A,形成循环等待。解决:统一资源访问顺序(如都先更新A再更新B)。2. 间隙锁死锁(MySQL特有)场景:MySQL的RR隔离级别下,更新非唯一索引列会加间隙锁(锁定范围内的空闲行),多个事务的间隙锁重叠导致死锁。解决:升级到RC隔离级别(禁用间隙锁);优化查询条件,使用唯一索引;减少事务的持有时间。3. 外键约束死锁场景:主表删除行时,会锁子表的对应行;如果子表有未提交的事务,主表删除会被阻塞,进而导致死锁。解决:禁用外键约束(不推荐,破坏数据一致性);先删除子表相关行,再删除主表行;使用ON DELETE CASCADE自动级联删除。 六、总结:吃一堑长一智的关键死锁的本质是资源竞争的闭环,预防的核心是减少竞争、统一顺序、缩短锁持有时间。记住以下几点:日志是关键:开启死锁日志记录,快速定位问题;设计优先:从事务粒度、访问顺序、索引优化入手,减少死锁可能;监控兜底:实时监控锁指标,提前预警;重试机制:应用程序必须有死锁重试逻辑,避免业务中断。通过以上体系化的方法,你可以从“被动救火”转向“主动预防”,大幅降低死锁的发生概率——毕竟,最好的解决是让死锁永远不会发生。————————————————                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                        原文链接:https://blog.csdn.net/ChailangCompany/article/details/153269415
  • [技术干货] 华为云高斯数据库实操与案例分享:开启企业级数据管理新篇章
    在数字化转型的浪潮中,数据已成为企业的核心资产。如何高效、安全、智能地管理和利用海量数据,是每个企业都必须面对的课题。华为云高斯数据库(GaussDB)作为一款领先的企业级分布式数据库,因其高性能、高可用、高安全及全栈自主创新等特性,正受到越来越多企业的青睐。本文将结合实操步骤与典型案例,带您深入了解高斯数据库的强大能力。一、 高斯数据库核心特性简介在进入实操之前,我们首先需要理解高斯数据库的“杀手锏”:存算分离架构: 计算节点与存储节点解耦,支持秒级弹性伸缩,可按需配置资源,极大降低成本。分布式强一致性: 在分布式部署下,依然保证数据的强一致性,确保业务逻辑准确无误。高可用与高可靠: 同城双活、异地容灾等多重高可用方案,RTO(恢复时间目标)和RPO(恢复点目标)近乎为零。全栈安全: 从芯片、硬件到软件、云服务的全栈安全防护,并提供数据加密、动态脱敏等高级安全特性。AI-Native内核: 将AI技术融入数据库内核,实现智能参数调优、智能索引推荐等,提升运维效率。二、 实操演练:从零开始使用高斯DB我们将以最常用的GaussDB(for MySQL) 为例,演示如何快速创建并连接一个数据库实例。步骤一:购买与配置实例登录华为云控制台,在产品列表中找到“数据库 > 云数据库 GaussDB”。点击“购买数据库实例”,进入配置页面。选择实例规格:数据库引擎: 选择“GaussDB(for MySQL)”。架构: 根据业务需求选择“主备”或“集群”(分布式)。CPU/内存: 根据业务负载选择,例如2 vCPUs / 4 GiB。存储空间: 选择SSD云盘,初始可选择100GB。设置网络与密码:选择或新建一个虚拟私有云(VPC)和子网,这是确保应用安全访问数据库的关键。设置数据库管理员账号(如root)的密码。确认订单并支付,等待约5-10分钟,实例状态变为“正常”即表示创建成功。步骤二:通过DAS连接并操作数据库华为云提供了便捷的数据管理服务(DAS),无需安装客户端,即可在浏览器中操作数据库。在实例列表中找到刚创建的实例,点击实例名称进入详情页。在左侧导航栏点击“登录”,选择“DAS登录”。输入创建时设置的密码,即可进入SQL操作界面。步骤三:执行基础SQL命令在DAS的SQL窗口中,我们可以执行标准的SQL语句来创建数据库、表和数据进行测试。sql 复制 下载-- 创建一个测试数据库CREATE DATABASE test_gaussdb;USE test_gaussdb;-- 创建一张用户表CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(100) UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);-- 插入测试数据INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com'),('李四', 'lisi@example.com');-- 查询数据SELECT * FROM users;执行成功后,您将看到插入的数据被正确返回。至此,您已经完成了高斯数据库最基础的创建、连接和操作流程。三、 案例分享:某大型制造企业的数据中台实践背景: 国内某大型制造企业,其ERP、MES、SCM等核心系统长期运行在传统商业数据库上,面临成本高昂、性能瓶颈和运维复杂三大难题。挑战:“分库分表”方案复杂,应用改造成本高。“双十一”式业务高峰期间,系统响应缓慢,影响生产排程。国外数据库License费用持续上涨,供应链风险加剧。解决方案:该企业选择华为云GaussDB作为其数据中台的统一数据存储引擎。平滑迁移: 利用华为云的数据复制服务(DRS),将原有数据库中的数据在线迁移至GaussDB(for openGauss)集群,迁移过程对业务影响极小。分布式架构: 采用GaussDB的分布式能力,将数十TB的业务数据自动分片到多个数据节点上,彻底解决了单机性能瓶颈。HTAP混合负载: 利用GaussDB的HTAP能力,一套数据库同时支撑前端业务的联机交易(OLTP)和后端管理层的实时分析报表(OLAP),省去了传统ETL流程,让决策者能看到分钟级的最新业务数据。成效:性能提升: 核心交易系统响应时间从秒级降至毫秒级,高峰时段运行平稳。成本优化: 总体拥有成本(TCO)相比原有方案下降超过50%。运维简化: 华为云提供了完善的监控、备份、弹性伸缩能力,企业数据库团队从繁重的日常运维中解放出来,更专注于业务创新。四、 总结通过以上实操和案例可以看出,华为云高斯数据库不仅技术先进、功能强大,更能通过其云原生特性,为企业提供极致的易用性和弹性。从简单的Web应用到复杂的核心业务系统,GaussDB都能提供坚实的数据底座支撑。对于寻求数字化转型、构建自主可控IT架构的企业而言,深入学习和应用华为云高斯数据库,无疑是一个极具战略价值的选择。建议读者可以亲自在华为云官网申请免费试用,通过实践来感受其魅力。
  • [问题求助] ECPG连接高斯数据库,测试环境正常访问,生产环境报-402无法连接数据库
    ECPG连接高斯数据库,测试环境正常访问,生产环境报-402无法连接数据库(ecpg需要头文件,库文件从数据库服务器/lib,/liclude获取,ecpg编译/链接均无问题))。生产环境telnet高斯数据库端口正常,gsql访问高斯数据库正常,ecpg 用户名/密码/数据库正确,数据库服务器未发现用户密码错等日志,测试和生产高斯数据库版本一致,建库脚本一致,麻烦大佬帮忙分析分析,可能是哪方面的问题,在此谢过了。
  • [数据库使用] extra_float_digits导致的double类型模糊匹配错误
    问题背景:select * from schema.tablename where  double::text like '%114.0061705';查询结果为空,但实际有符合条件的数据。根因:double类型的数值,在进行模糊查询时,由于extra_float_digits导致精度不一致,结果集出现误差。 extra_float_digits参数说明:调整浮点值显示的数据位数,浮点类型包括float4、float8 以及几何数据类型。参数值加在标准的数据位数上(FLT_DIG或DBL_DIG中合适的)。参数类型:USERSET取值范围:整型,-15~3说明:设置为3,表示包括部分有效的数据位。对转储需要精确恢复的浮点数据尤其有用。设置为负数,表示摒弃不需要的数据位。默认值:0 通过JDBC进行连接DWS时,需要注意。连接参数第三方工具通过JDBC连接时,JDBC向DWS发起连接请求,会默认添加以下配置参数,详见JDBC代码ConnectionFactoryImpl类的实现。params = { { "user", user }, { "database", database }, { "client_encoding", "UTF8" }, { "DateStyle", "ISO" }, { "extra_float_digits", "3" }, { "TimeZone", createPostgresTimeZone() }, };这些参数可能会导致JDBC客户端的行为与gsql客户端的行为不一致,例如,Date数据显示方式、浮点数精度表示、timezone显示。如果实际期望和这些配置不符,建议在java连接设置代码中显式设定这些参数。通过JDBC连接数据库时,会设置extra_float_digits=3,DWS中设置为extra_float_digits=0,可能会造成同一条数据在JDBC显示和gsql显示的精度不同。对于精度敏感的场景,建议使用numeric类型。
  • [问题求助] 数据迁移
    目前我想做迁移的实验,需要在Oracle和MySQL创建大量的表,索引等对象,有什么方式可以模拟真实的生产环境吗
  • [技术干货] 大数据干货合集(2025年9月)
    锁相关视图cid:link_1锁相关参数介绍cid:link_2自动处理单点死锁cid:link_3分布式死锁cid:link_4pooler连接池详解cid:link_5postgres工作线程cid:link_6Pooler 连接池复用流程cid:link_7Pooler 连接清理cid:link_8Stream 线程cid:link_0idleRing的作用cid:link_9数据结构设计cid:link_10Stream 线程状态转移DFA设计cid:link_11单个Stream线程执行流程cid:link_12通过表象看Stream线程池逻辑cid:link_13建立多用户场景https://bbs.huaweicloud.com/forum/thread-0243194537401613171-1-1.html
  • [技术干货] 建立多用户场景
    Create user ***;(建立多用户) 分别执行带Stream算子的查询;(参考场景一示例) 查询结束,查pgxc_thread_wait_status看DN节点:预期Stream线程状态为wait thread cond。且多user之间Stream线程可以复用。 例:用户一执行完查询,视图中显示共有四个Stream线程在线程池,用户二执行同样查询返回正确结果,视图中的Stream线程个数不变,且线程号也是一致的,则说明复用。 集群基础行为场景——线程清理场景 调整guc 参数 max_stream_pool 的值,观测是否生效;预期:当设置max_stream_pool 小于当前 idle 线程个数,支持线程个数实时减少;当设置max_stream_pool大于当前idle线程个数,将由业务驱动线程个数的增加,但是不会超过max_stream_pool。 执行 clean connection(ALL force),查看 Stream 线程是否被清理;预期:该database 的Stream线程被完全清理。 执行drop database命令,查看Stream线程是否被清理;预期:该database的Stream 线程被完全清理。 
  • [技术干货] 通过表象看Stream线程池逻辑
    max_stream_pool:设置 Stream线程池能够容纳Stream线程的最大个数。该参数8.1.2 及以上版本支持。默认值为65535。设置为-1表示不开启Stream线程池。该参数支持reload更新,更新规则:设置max_stream_pool小于当前可用线程个数,支持线程个数实时减少;当设置max_stream_pool大于当前idle线程个数,将由业务驱动线程个数的增加。wait stream task:空闲的Stream线程; wait node:等待其他DN的数据,需要关注对端状态; flush data:发送数据给其他DN时因为对端buffer满而阻塞; wait cmd:DN上空闲的postgres线程,等待CN的下一个query; none:未定义状态,极有可能是阻塞原因; synchronize quit:同步退出状态,自身任务已完成,在等待同一个query的其他线程一起退出。Create database ***;(建立多库) 分别执行带Stream算子的查询; 查询结束,查pgxc_thread_wait_status看DN节点:预期Stream线程状态为wait thread cond。且多database之间Stream线程不复用。 例:create table test_01(c1 int, c2 int)with(orientation=column) distribute by hash(c1); insert into test_01 select generate_series(1,100), generate_series(1,100);analyze test_01; select * from test_01 a, test_01 b, test_01 c, test_01 d, test_01 e, test_01 f where a.c2 =b.c2 and c.c2 = d.c2 and e.c2=f.c2 limit 100;
  • [技术干货] 单个Stream线程执行流程
    Stream 线程初始化仅初始化一次,执行完query之后,便将连接归还到连接池里,循环执行上图中黄色部分的语句,如果有异常则线程退出,连接销毁,slot 归还至emptyRing;如果正常执行结束,将连接中内容清理,避免下个连接误用,并将slot归还至idleRing 等待下个连接复用。 那么Stream线程复用时如何保持参数的一致性呢,对应上图中的set GUC params阶段。父线程保存自己的guc_variables在syncGucVariables中,syncGucVariables是需要传递给 Stream 的结构用以保证父子线程 guc 参数的一致。然后父线程在初始化StreamProducer 时将 syncGucVariables 保存在该结构中传递。Stream 线程根据StreamProducer 初始化自己的 syncGucVariables 变量,首先 reset 所有的 guc 变量,然后根据syncGucVariables修正自己的variables。 STREAM_SLOT_EXIT:idleRing(idle 线程超时)、emptyRing(初始化或者FATAL); STREAM_SLOT_IDLE:idleRing STREAM_SLOT_HOLD:运行空间(从无锁队列中取出)、idleRing(idle线程超时或中断); STREAM_SLOT_RUN:运行空间。 根据各状态所处的位置情况,从idleRing中取出的slot可能有三种状态:EXIT、IDLE、HOLD。当取出IDLE状态的slot,说明线程可复用;当取出EXIT状态的slot,说明线程已退出,此时需要将slot转存到emptyRing;当取出HOLD状态,说明线程正在被使用,此时需要放回idleRing。 
  • [技术干货] Stream 线程状态转移DFA设计
    每一个记录线程信息的结构ThreadSlot中都保存了线程当前的状态status,记录线程状态的目的是为了保障线程执行过程的有序控制,也可以通过状态的互斥避免threadSlot 不会被两个线程同时使用。 Stream 线程状态转移用确定性有限状态机(DFA,definite automata)表征,共包含 4 个状态:STREAM_SLOT_EXIT 、 STREAM_SLOT_IDLE 、STREAM_SLOT_HOLD和STREAM_SLOT_RUN状态。其物理含义如下: STREAM_SLOT_EXIT:线程退出状态,表示线程未被创建或线程已退出; STREAM_SLOT_IDLE:线程可复用状态,表示线程在idleRing中,可以被复用; STREAM_SLOT_HOLD:线程临时独占状态,表示线程在做进入下一个状态的准备工作; STREAM_SLOT_RUN:线程运行状态,表示线程正在执行任务。与状态对应的,是 slot 所处的位置,slot 所处的位置有三处,分别是 idleRing、emptyRing和运行空间,slot从无锁队列中拿出,运行时所处的位置,我们称之为运行空间。
  • [技术干货] 数据结构设计
    定义结构体ThreadSlot保存线程池中每一个线程的信息,包含:线程状态、线程号、线程对应的database oid、线程执行所需的信息StreamProducer,StreamProducer是父线程向子线程传递的唯一结构、线程唤醒所需的锁和条件变量。 定义结构体 StreamThreadPool 表征线程池,其中 size 表示线程池中拟预留的ThreadSlot 个数,ThreadSlot被保存在threadSlots数组中;无锁队列emptyRing用来保存未创建线程ThreadSlot,对应地,idleRing 用来保存空闲的已创建Stream线程的ThreadSlot。定义结构体StreamPool,由 于 Stream线程的初始化信息和database是强相关的,如果不保留 database 相关的信息,那么线程初始化的时间代价仍然较高,所以线程池中的线程复用时,需要满足database信息匹配,所以一个emptyRing 和一个database相匹配,保存在链表PoolListHead中。 
  • [技术干货] idleRing的作用
    Stream 线程池为了高效管理线程的出/入池操作,采用无锁队列实现。定义结构体ThreadSlot 保存线程池中每一个线程的信息,包含:线程状态、线程号、线程对应的database oid、线程执行所需的信息StreamProducer、线程唤醒所需的锁和条件变量。 当线程还未被创建时,初始化一定数量的ThreadSlot数量以预留Stream线程,这些ThreadSlot 被保存在数组threadSlots中 。当 Stream线程执行完毕,需要将Stream线程放置到表征可复用线程的无锁队列,称之为 idleRing;当线程因为超时、异常等原因不再复用,需要退出时,将Stream线程对应的ThreadSlot放置到表征未创建线程的无锁队列,称之为emptyRing。 idleRing 的作用是为了快速获取并复用线程池中的线程,emptyRing的作用是快速获取一个未被使用的ThreadSlot结构,以创建一个新的Stream线程。由于Stream线程的初始化信息和database是强相关的,如果不保留database相关的信息,那么线程初始化的时间代价仍然较高,所以线程池中的线程复用时,需要满足 database 信息匹配。对于设计线程池而言,每一个database都应该对应一个idleRing。 
  • [技术干货] Stream 线程
    Stream 线程是临时线程,随query启动和退出,负责Stream算子的执行,Stream线程初始化和退出都会争抢锁等进程级资源,在 Stream 线程个数无法进一步优化的场景下,需要设计有效方案以减少 Stream 线程初始化和退出的时间代价,将进程初始化耗时稳定在ms级,保障数据库的确定性时延查询。Stream 线程池的核心思想是等 Stream线程执行完计划任务,保留必要且可复用的线程信息,将线程放入线程池中。 线程池中的线程执行过程如上图所示,其具体步骤为: 步骤一:线程信息初始化; 步骤二:线程待唤醒后轻量级初始化(query级初始化); 步骤三:线程任务执行; 步骤四:线程清理; 返回步骤二:继续等待下条query执行。 在返回步骤二时,当线程等待超时、超出线程池容量(最大Stream线程个数)、异常时线程已不可用,需要销毁。 其中步骤一中在线程初始化时,需要执行的操作有:线程创建、创建相关内存上下文、信号处理函数注册、内存追踪信息初始化、初始化GUC选项等操作; 步骤二中在线程轻量级/查询级初始化时,需要执行的操作有恢复GUC参数、初始化BackendParams、重置GUC参数等操作。
  • [技术干货] Pooler 连接清理
    清理Session持有的连接 cache_connection,是否使用pooler连接池缓存连接,默认开; session_timeout,客户端连接空闲超时后报错退出归还连接; enable_force_reuse_connections,事务结束后强制归还连接; conn_recycle_timeout(8.2.1), CN 空闲session超时后归还连接。pg_clean_free_conn视图/函数,清理1/4的空闲连接池连接,CM定期调用;CLEAN CONNECTION 语法,清理对应DB或user的所有空闲连接 clean connection to all for database postgres to USER user1。GaussDB(DWS)分布式架构的Stream 算子作为SQL join操作时频繁发生的执行算子,共存在三种模式:Gather、Redistribute、Broadcast,分别负责CN节点GATHER数据,DN节点REDISTRIBUTE和BROACAST数据。大集群高并发场景下,Stream算子过多可能会导致通信的性能瓶颈,引起性能劣化(2000个stream同时启动,进程初始化耗时从ms级劣化到s级),因此需要尽可能减少Stream算子。但是在某些现场环境下,存在数据倾斜、join查询不包含必要分布键等客观情况,Stream算子无法有效减少,为多表join 场景下的查询时延保障带来挑战。因此 GaussDB(DWS)对于线程初始化->线程任务执行->线程退出执行的流程方面做了stream线程池优化,减少了线程初始化与线程退出所带来的开销。
总条数:1672 到第
上滑加载中