首页 / 资讯中心 / 文章详情

Delphi FireDAC连接池高并发配置避坑实战手册

Delphi FireDAC连接池高并发配置避坑实战手册 ★ FEATURED ARTICLE
简介这份PDF文档面向使用Delphi进行企业级应用开发的技术人员尤其是需要应对高并发数据库访问场景的开发者、架构师与DBA聚焦FireDAC连接池配置中的常见陷阱与优化思路。文档共54页围绕连接池基础原理、核心参数详解、多数据库类型配置差异、性能优化策略、常见问题排查及监控自动化等模块展开对MaxConnections、ConnectionLifeTime、RetryConnectCount等关键参数逐一剖析并给出连接泄漏、死锁、超时等典型故障的诊断与修复路径。资源包为单一PDF文件大小约4.51MB支持目录章节跳转与阅读器左侧大纲快速定位文字、图表、函数与目录显示完整条理清晰。目前已有193人学习查阅适合希望系统掌握FireDAC高并发配置、避开常见坑点并提升数据库访问稳定性的中高级Delphi开发者参考。1. 从一次连接池耗尽说起这份手册到底能解决什么凌晨两点监控告警突然炸了——生产环境的订单服务大面积超时日志里清一色[FireDAC][Phys][MySQL] Too many connections。排查到天亮才发现问题不在 SQL 慢查询也不在数据库服务器配置而是 FireDAC 连接池的MaxPoolSize设成了默认值而业务侧一个没关好的TFDQuery把连接全占死了。这种翻车场景在 Delphi 企业级项目里几乎每个团队都遇到过至少一次。这份《Delphi数据库连接池FireDAC高并发配置避坑手册》就是冲着这类问题来的。它不是 FireDAC 的 API 字典而是一份围绕高并发场景、把连接池参数讲透、把配置陷阱标出来的实战文档。全文 54 页覆盖从连接池工作原理、核心参数详解到多数据库配置差异、动态调优、监控集成和故障排查的完整链路。适合两类人一是刚接手 Delphi 项目、对 FireDAC 连接池只有模糊认知的开发者二是已经在生产环境跑着高并发服务、被连接泄漏和超时问题反复折磨的架构师。如果你正在用 Delphi 10.4 Sydney 及以上版本、FireDAC 2.0 及以上版本做多平台数据访问这份手册里的参数表和配置模板可以直接抄作业。2. FireDAC 连接池的底层逻辑为什么你的配置总是不生效很多开发者配连接池的方式是“照着别人的参数抄一遍”结果发现同样的MaxPoolSize50在 A 项目跑得好好的到 B 项目就频繁超时。根本原因在于没搞懂 FireDAC 连接池的复用机制和参数之间的联动关系。这一章把底层逻辑拆开后面配参数时才知道每个数字在影响什么。2.1 连接池的获取与归还路径FireDAC 的连接池不是独立进程它由TFDConnection组件内部维护。当你调用FDConnection.Open时实际发生的是FireDAC 先检查当前连接定义对应的池中是否有空闲连接有就直接复用没有就根据MaxPoolSize判断是否创建新连接。关键点在于——连接归还发生在FDConnection.Close或组件释放时而不是查询结束后。这意味着如果你在一个方法里Open了连接、执行完查询却没有Close这个连接会一直被标记为“使用中”池里可用连接数只减不增。常见做法是配合TFDQuery的Connection属性自动管理但更稳妥的方式是在try...finally里显式关闭。下面这段代码展示了标准的获取与归还路径procedure TDataModule1.ExecuteQuerySafely; begin FDConnection1.Open; // 从池中获取连接无空闲则按 MaxPoolSize 创建 try FDQuery1.Connection : FDConnection1; FDQuery1.SQL.Text : SELECT * FROM orders WHERE status :status; FDQuery1.ParamByName(status).AsString : pending; FDQuery1.Open; // 处理结果集 finally FDQuery1.Close; FDConnection1.Close; // 关键归还连接到池而非物理断开 end; end;逻辑说明FDConnection1.Open触发池的获取逻辑FDConnection1.Close触发归还逻辑。参数MaxPoolSize控制池的上限MinPoolSize控制初始化时预创建的连接数。如果MinPoolSize5、MaxPoolSize50启动时池里就有 5 个连接待命并发上来后逐步扩展到 50 个超过 50 的请求会进入等待队列等待时间由ConnectionTimeout决定。2.2 连接生命周期与空闲回收的联动ConnectionLifeTime和ConnectionIdleTime是两个最容易配错的参数。前者控制连接从创建到被强制回收的总时长后者控制连接在池中空闲多久后被释放。很多开发者把ConnectionLifeTime设得很大比如 86400 秒以为这样能减少重连开销结果遇到数据库服务器端的wait_timeout先到期连接被服务器单方面断开客户端却不知道拿到的就是一个“死连接”。正确的做法是让ConnectionLifeTime小于数据库服务器的超时时间。以 MySQL 为例默认wait_timeout是 28800 秒8 小时那么ConnectionLifeTime建议设在 3600 到 7200 秒之间。ConnectionIdleTime则根据业务波峰波谷来定——如果夜间几乎没有请求设成 300 到 600 秒可以让池自动收缩释放数据库资源。// 连接生命周期与空闲回收的推荐配置 FDConnection1.Params.Values[Pooled] : True; FDConnection1.Params.Values[MinPoolSize] : 5; FDConnection1.Params.Values[MaxPoolSize] : 50; FDConnection1.Params.Values[ConnectionLifeTime] : 3600; // 1小时强制回收 FDConnection1.Params.Values[MaxIdleTime] : 600; // 10分钟空闲回收 FDConnection1.Params.Values[CheckConnectionSQL] : SELECT 1; // 取连接时验证参数说明CheckConnectionSQL是容易被忽略但极其重要的参数。设置后FireDAC 在从池中取出连接时会先执行这条 SQL 验证连接是否仍然有效无效则丢弃并创建新连接。对于 MySQL 用SELECT 1Oracle 用SELECT 1 FROM DUALPostgreSQL 同样用SELECT 1。这个验证会带来极小的性能开销但能避免大量“连接已断开”的运行时异常。2.3 连接池与其他数据访问组件的选型差异在 Delphi 生态里BDE 已经停止更新ADO 依赖 Windows COM 组件无法跨平台dbExpress 虽然轻量但连接池功能薄弱。FireDAC 的优势在于内置了完整的池化管理器且跨平台支持 Windows、macOS、Linux、iOS、Android。如果你的项目需要同时部署到 Windows 服务器和 Linux 容器FireDAC 是唯一不需要改数据访问层代码的选择。选型时还要注意FireDAC 的连接池是进程内池不是跨进程的中间件池。这意味着每个应用实例独立维护自己的连接池部署多个实例时数据库的总连接数等于实例数乘以单实例的MaxPoolSize。这一点在容器化部署时尤其要算清楚否则数据库的max_connections会被瞬间打满。3. 高并发核心参数拆解从 MaxPoolSize 到 Failover 的配置清单参数配错一个高并发下就是连锁反应。这一章把 FireDAC 连接池的参数分成四组——连接管理、复用回收、错误重试、负载均衡——每组给出推荐值、调整逻辑和代码模板。参数值不是固定的但调整的方向和边界是明确的。3.1 连接管理参数MaxPoolSize 不是越大越好MaxPoolSize的设置需要同时考虑三个约束数据库服务器的max_connections、应用实例数量、单请求持有连接的平均时长。一个实用的估算公式是MaxPoolSize (数据库最大连接数 × 0.8) / 应用实例数。比如 MySQL 的max_connections500部署 4 个应用实例那么每个实例的MaxPoolSize建议不超过 100。设成 200 的后果是四个实例同时打满数据库直接拒绝新连接所有实例一起报错。MinPoolSize的设置逻辑不同它影响的是冷启动延迟。如果业务有明显的早高峰建议把MinPoolSize设为日常平均并发连接数的 60% 到 80%这样早高峰来临时不需要大量创建新连接。但MinPoolSize设得太高低峰期会浪费数据库资源。一个折中方案是配合动态调整策略在检测到负载因子超过 0.8 时临时提升MaxPoolSize。// 连接管理参数配置模板 FDConnection1.Params.Values[Pooled] : True; FDConnection1.Params.Values[MinPoolSize] : 10; // 日常平均并发的60% FDConnection1.Params.Values[MaxPoolSize] : 80; // (500*0.8)/4100留余量 FDConnection1.Params.Values[ConnectionTimeout] : 15; // 获取连接超时秒数 FDConnection1.Params.Values[LoginTimeout] : 10; // 登录超时秒数参数说明ConnectionTimeout是从池中获取连接的超时时间超时后抛出异常。这个值不宜设得太小否则高并发时大量请求在等待队列中就被判超时也不宜太大否则连接泄漏时请求会长时间挂起。15 到 30 秒是常见区间。LoginTimeout是建立物理连接的超时时间与ConnectionTimeout不同它只在创建新连接时生效。3.2 复用回收与错误重试RetryConnectCount 的指数退避ReuseConnections参数控制是否启用连接复用。在 FireDAC 中这个参数通常与Pooled配合使用。当PooledTrue时连接复用是默认行为但某些场景下比如需要完全隔离的会话状态可以显式关闭。RetryConnectCount和RetryConnectDelay是错误处理的关键参数。网络抖动或数据库短暂不可用时合理的重试策略能让应用自动恢复而不是直接抛异常给用户。重试策略推荐指数退避第一次重试等待 1 秒第二次 2 秒第三次 4 秒。FireDAC 的RetryConnectDelay是固定间隔如果需要指数退避需要在OnError事件中自己实现。下面是一个结合了重试和异常处理的配置示例// 错误重试与异常处理配置 FDConnection1.Params.Values[RetryConnectCount] : 3; FDConnection1.Params.Values[RetryConnectDelay] : 1000; // 基础间隔1秒 FDConnection1.Params.Values[KeepConnection] : True; // 保持连接活跃 procedure TDataModule1.FDConnection1Error(ASender: TObject; const AInitiator: IFDStanObject; var AException: Exception); begin // 记录异常上下文便于排查 Logger.Log(Format(连接异常: %s, 错误码: %d, [AException.Message, FDConnection1.RowsAffected])); // 如果是连接断开类异常标记需要重建连接 if Pos(lost connection, LowerCase(AException.Message)) 0 then FNeedReconnect : True; end;逻辑说明RetryConnectCount3表示连接失败后最多重试 3 次。KeepConnectionTrue让 FireDAC 在连接空闲时不主动断开减少冷启动延迟但要注意数据库服务器的会话数限制。OnError事件是捕获连接异常的入口在这里记录日志比在全局异常处理中记录更精准因为能拿到 FireDAC 内部的错误上下文。3.3 负载均衡与故障转移Failover 配置的边界Failover参数用于配置备用数据库服务器主服务器不可用时自动切换。配置格式是分号分隔的服务器列表。但要注意FireDAC 的故障转移是连接级别的不是事务级别的。如果主服务器在事务执行中途宕机已经执行的部分不会自动回滚到备用服务器需要应用层自己处理事务补偿。LoadBalance参数启用后FireDAC 会在多个服务器之间轮询分配连接。这个功能适合读多写少的场景比如报表查询可以分散到多个只读副本。但写操作必须指向主库所以实际使用时通常需要配置两组连接定义一组启用LoadBalance用于读一组不启用用于写。// 故障转移与负载均衡配置 FDConnection1.Params.Values[Failover] : Serverdb-backup1;Serverdb-backup2; FDConnection1.Params.Values[LoadBalance] : True; // 动态切换连接定义读写分离场景 procedure TDataModule1.SwitchToReadOnly; begin FDConnection1.Connected : False; FDConnection1.ConnectionDefName : ReadOnlyPool; // 指向只读副本组 FDConnection1.Connected : True; end;参数说明Failover的服务器列表按顺序尝试第一个可用即使用。LoadBalanceTrue时FireDAC 会在ConnectionDefs中注册的多个服务器之间轮询。动态切换连接定义时必须先Connected : False再改ConnectionDefName否则新定义不会生效。这个操作会触发一次连接归还和重新获取在高并发下要避免频繁切换。3.4 多数据库配置差异对照表不同数据库对连接池参数的支持和推荐值差异很大。下面这张表整理了 MySQL、PostgreSQL、Oracle 三种常见数据库在 FireDAC 下的关键配置差异直接对照修改即可。参数MySQLPostgreSQLOracleDriverIDMySQLPGOra推荐 MaxPoolSize30默认 max_connections1515020连接资源消耗大ConnectionLifeTime3600小于 wait_timeout72003600MaxIdleTime180036001800CheckConnectionSQLSELECT 1SELECT 1SELECT 1 FROM DUAL字符集参数CharacterSetutf8mb4无需额外设置无需额外设置特殊注意连接数不超过 151支持更多并发连接每个连接消耗更多内存提示Oracle 的FetchOptions.RowsetSize建议设为 100 到 200因为 Oracle 的网络往返开销较大批量获取能显著减少延迟。MySQL 和 PostgreSQL 可以设到 500 到 1000。4. 从零配置一个可用的连接池代码模板与验证步骤参数表看完了但真正落到代码里顺序和初始化时机同样关键。这一章给出一个完整的、可以直接复制到项目里的连接池配置模板然后说明如何验证配置是否生效。4.1 连接定义创建与池参数注入第一步是在TFDConnection的Params中注入池参数。注意Pooled参数必须在Open之前设置Open之后再改不会生效。连接定义可以通过FDManager.ConnectionDefs动态注册也可以在设计器中预先配置。动态注册的好处是可以在运行时根据环境变量切换数据库地址。procedure TDataModule1.InitConnectionPool; begin // 动态注册连接定义 FDManager.ConnectionDefs.AddConnectionDef( OrderDB, MySQL, Server127.0.0.1;Port3306;Databaseorder_db; User_Nameapp_user;Passwordapp_pass; ); // 注入池参数 FDConnection1.ConnectionDefName : OrderDB; FDConnection1.Params.Values[Pooled] : True; FDConnection1.Params.Values[MinPoolSize] : 5; FDConnection1.Params.Values[MaxPoolSize] : 50; FDConnection1.Params.Values[ConnectionLifeTime] : 3600; FDConnection1.Params.Values[MaxIdleTime] : 600; FDConnection1.Params.Values[CheckConnectionSQL] : SELECT 1; FDConnection1.Params.Values[ConnectionTimeout] : 15; // 打开连接触发池初始化 try FDConnection1.Open; Logger.Log(连接池初始化成功当前池大小: IntToStr(FDConnection1.GetPooledConnectionsCount)); except on E: Exception do Logger.Log(连接池初始化失败: E.Message); end; end;逻辑说明AddConnectionDef注册了一个名为OrderDB的连接定义指定了 MySQL 驱动和连接字符串。FDConnection1.ConnectionDefName指向这个定义后Params中的池参数会覆盖连接定义中的默认值。Open调用触发池的初始化此时MinPoolSize5个连接会被预创建。GetPooledConnectionsCount返回当前池中的连接总数可以用来验证初始化是否按预期执行。4.2 连接池健康检查与动态调整连接池跑起来之后需要定期做健康检查并在负载变化时动态调整池大小。健康检查的逻辑是遍历池中所有连接对每个连接执行CheckConnectionSQL失败的连接标记为无效并重置。动态调整则根据当前活跃连接数与MaxPoolSize的比值来决定是否扩容或缩容。procedure TDataModule1.HealthCheckAndAdjust; var ActiveCount, MaxCount: Integer; LoadFactor: Double; begin ActiveCount : FDConnection1.GetPooledConnectionsCount; MaxCount : StrToInt(FDConnection1.Params.Values[MaxPoolSize]); LoadFactor : ActiveCount / MaxCount; // 负载超过80%扩容 if LoadFactor 0.8 then begin MaxCount : MaxCount 10; FDConnection1.Params.Values[MaxPoolSize] : IntToStr(MaxCount); Logger.Log(连接池扩容至: IntToStr(MaxCount)); end // 负载低于30%且池大小超过最小值10缩容 else if (LoadFactor 0.3) and (MaxCount 20) then begin MaxCount : MaxCount - 5; FDConnection1.Params.Values[MaxPoolSize] : IntToStr(MaxCount); Logger.Log(连接池缩容至: IntToStr(MaxCount)); end; // 验证所有连接的健康状态 FDConnection1.ExecSQL(SELECT 1); end;参数说明GetPooledConnectionsCount返回的是池中当前连接总数包括空闲和使用中的。负载因子用这个值除以MaxPoolSize来估算。扩容步长设为 10缩容步长设为 5避免频繁调整导致抖动。缩容的下限是MinPoolSize 10防止把池缩到太小导致后续请求等待。健康检查用ExecSQL(SELECT 1)是最轻量的方式但只验证了当前连接要验证所有连接需要遍历池对象。4.3 配置生效的验证方法配完参数后怎么确认池真的在工作三个验证点第一启动后立即查看GetPooledConnectionsCount应该等于MinPoolSize第二并发执行 100 个查询观察池大小是否增长到接近MaxPoolSize后不再增长第三手动关闭一个连接后池大小应该减少再次请求时重新增长。如果池大小始终等于MinPoolSize不变化说明Pooled参数没生效检查是否在Open之前设置。// 验证连接池是否生效的测试代码 procedure TDataModule1.VerifyPoolBehavior; var I: Integer; InitialCount, AfterLoadCount: Integer; begin InitialCount : FDConnection1.GetPooledConnectionsCount; Logger.Log(初始池大小: IntToStr(InitialCount)); // 模拟并发请求 for I : 1 to 100 do begin FDConnection1.Open; try FDConnection1.ExecSQL(SELECT 1); finally FDConnection1.Close; end; end; AfterLoadCount : FDConnection1.GetPooledConnectionsCount; Logger.Log(负载后池大小: IntToStr(AfterLoadCount)); if AfterLoadCount InitialCount then Logger.Log(连接池工作正常已按需扩展) else Logger.Log(警告连接池可能未生效检查 Pooled 参数); end;逻辑说明这段代码先记录初始池大小然后循环 100 次执行“获取连接-执行查询-归还连接”的操作。如果池正常工作AfterLoadCount应该大于InitialCount因为池会保留已创建的连接以备复用。如果两者相等说明每次都在创建新连接并立即销毁Pooled参数可能没有正确设置。5. 避坑与排查连接池耗尽、泄漏、死锁的现场处理参数配好了代码也写了但生产环境的问题往往不按手册出牌。这一章整理了四个最常见的连接池故障场景每个都按“现象 → 原因 → 解决”的结构给出排查路径。这些坑我都在项目里踩过有些是配置问题有些是代码习惯问题。5.1 连接池耗尽Too many connections 的连锁反应现象应用日志出现[FireDAC][Phys][MySQL] Too many connections所有数据库操作超时重启应用后短暂恢复几分钟后再次出现。原因三种可能。一是MaxPoolSize设得太大多个应用实例同时打满数据库的max_connections二是连接泄漏某个代码路径Open后没有Close连接被永久占用三是数据库服务器的wait_timeout小于ConnectionLifeTime连接被服务器断开后客户端不知道仍然认为连接可用。解决先查数据库的SHOW PROCESSLIST看连接来自哪些应用实例确认是单实例问题还是全局问题。如果是全局问题降低每个实例的MaxPoolSize公式是(max_connections × 0.8) / 实例数。如果是单实例问题检查代码中所有FDConnection.Open是否都有对应的Close推荐用try...finally包裹。如果是超时不一致问题把ConnectionLifeTime设为小于wait_timeout的值并启用CheckConnectionSQL。5.2 连接泄漏连接数只增不减的隐形杀手现象应用运行一段时间后池中连接数持续增长最终达到MaxPoolSize后新请求全部超时。重启后恢复但再次缓慢增长。原因连接泄漏几乎总是代码问题。最常见的三种在except块中忘记Close在循环中Open了连接但只在循环外Close一次使用TFDQuery时没有设置Connection属性导致每次查询都创建新连接。解决用 FireDAC 的OnConnectionStateChange事件监控连接状态变化记录每次Open和Close的调用栈。更直接的方法是在代码审查中强制要求所有Open必须出现在try块的第一行Close出现在finally块的第一行。下面是一个防泄漏的代码模板// 防连接泄漏的标准写法 procedure TDataModule1.SafeQuery; begin FDConnection1.Open; try FDQuery1.Connection : FDConnection1; // 必须显式指定 try FDQuery1.SQL.Text : SELECT COUNT(*) FROM orders; FDQuery1.Open; // 处理结果 finally FDQuery1.Close; end; finally FDConnection1.Close; // 确保任何异常下都会归还连接 end; end;5.3 高并发死锁连接池与事务的交叉等待现象高并发下部分请求卡死数据库端出现死锁告警应用日志显示事务等待超时。原因连接池中的连接被事务长时间持有其他请求等待连接释放而持有连接的请求又在等待数据库锁释放形成交叉等待。典型场景是事务 A 持有连接 1 并等待行锁事务 B 持有行锁并等待连接 2而连接 2 被事务 A 占用。解决缩短事务持有连接的时间。具体做法事务中只包含必要的 SQL 操作不要在事务中做网络调用或文件 IO设置CommandTimeout限制单条 SQL 的执行时间对于批量操作分批提交而不是一个大事务包到底。FireDAC 的Transaction对象支持StartTransaction和Commit确保每个事务都有明确的边界。5.4 连接超时ConnectionTimeout 与网络抖动的博弈现象偶发性连接超时日志显示ConnectionTimeout expired但数据库服务器负载正常。原因ConnectionTimeout设得太小高并发时请求在池的等待队列中排队还没轮到就被判超时。或者网络存在间歇性抖动物理连接建立时间超过LoginTimeout。解决把ConnectionTimeout从默认的 10 秒调整到 15 到 30 秒给等待队列留出缓冲。同时启用RetryConnectCount让超时后的请求自动重试。如果是网络抖动问题检查应用服务器和数据库服务器之间的网络质量必要时增加LoginTimeout到 15 秒。注意ConnectionTimeout和LoginTimeout是两个不同的参数前者管获取连接后者管建立物理连接。注意排查连接超时问题时先看数据库服务器的Threads_connected和Threads_running如果这两个值远低于max_connections说明瓶颈在应用侧的池配置而不是数据库。6. 进阶用事件监控和日志把连接池变成白盒连接池配好之后最怕的是出问题时看不到内部状态。FireDAC 提供了一组事件接口可以在连接获取、归还、创建、销毁时触发回调把这些事件接到日志系统里连接池就从黑匣子变成了白盒。这一章给出一个基于事件的监控实现以及如何把监控数据输出到日志和告警系统。6.1 用 OnConnectionStateChange 追踪连接流转TFDConnection的OnConnectionStateChange事件在连接状态变化时触发可以拿到当前是获取还是归还、连接是否有效。把这个事件接到日志里每次连接流转都有记录排查泄漏时直接看日志就能定位到哪次Open没有对应的Close。procedure TDataModule1.FDConnection1StateChange(Sender: TObject); var StateStr: string; begin case FDConnection1.State of csInactive: StateStr : 未连接; csOpening: StateStr : 正在打开; csOpen: StateStr : 已连接; csClosing: StateStr : 正在关闭; csClosed: StateStr : 已关闭; end; Logger.Log(Format([连接池] 状态变化: %s, 池大小: %d, 时间: %s, [StateStr, FDConnection1.GetPooledConnectionsCount, FormatDateTime(yyyy-mm-dd hh:nn:ss.zzz, Now)])); end;逻辑说明OnConnectionStateChange在Open和Close时都会触发通过State属性区分当前状态。日志中记录池大小和时间戳如果发现池大小持续增长而状态在csOpen和csClosed之间频繁切换说明连接创建和销毁的频率过高可能需要调大MinPoolSize。如果池大小只增不减说明存在泄漏。6.2 自定义监控指标与告警阈值除了日志还可以把连接池的关键指标暴露给外部监控系统。FireDAC 没有内置的 Prometheus 接口但可以通过定时采样把指标写入日志文件再由日志采集器转发。关键指标包括当前池大小、活跃连接数、等待队列长度、连接创建速率、连接销毁速率。指标采集方式告警阈值含义池大小GetPooledConnectionsCount持续等于 MaxPoolSize 超过 5 分钟池已打满请求在排队活跃连接数池大小 - 空闲连接数超过 MaxPoolSize 的 90%接近容量上限连接创建速率单位时间内 Open 次数超过 10 次/秒池太小或泄漏连接销毁速率单位时间内 Close 次数与创建速率严重不匹配可能存在泄漏等待超时次数ConnectionTimeout 异常计数超过 5 次/分钟池容量不足或泄漏采集这些指标的方式是在OnConnectionStateChange中累加计数器然后每分钟输出一次汇总日志。告警阈值可以根据实际业务调整但“池大小持续等于 MaxPoolSize”是最关键的信号出现这个信号说明池已经不够用了。6.3 一个具体的调优习惯从那以后我每次上线新的 Delphi 服务都会强制走一遍连接池压测用 200 个并发线程跑 10 分钟观察池大小的变化曲线。如果曲线在 5 分钟内就冲到MaxPoolSize并保持水平说明池太小或者有泄漏如果曲线在MinPoolSize和MaxPoolSize之间平稳波动说明配置合理。压测时还会故意杀掉一个数据库连接验证CheckConnectionSQL是否能自动剔除死连接。这个习惯帮我提前发现了至少三次潜在的连接泄漏比等到生产环境告警再排查省了太多时间。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站