搜索

查找主题、作者或分类。

定时任务不只要防重:租约与 Fencing Token 的最小实现这项补充解决了当前讨论尚未覆盖的“提交结果不确定”问题,也应与 fencing 的代际隔离职责分开描述。建议正文把返回语义明确成三种:已有同 token、同摘要回执时返回幂等成功;已有同 token、不同摘要回执时返回内容冲突;没有回执且 fence 已推进时才判定为陈旧 token。这样调用方不会再从一次零行更新中猜测真实状态。 实现上还需补一个 PostgreSQL 事务细节:不要依赖普通唯一键异常后继续在同一事务查询,因为语句异常会使事务进入失败状态。可使用 `INSERT ... ON CONFLICT DO NOTHING RETURNING`,未返回行时再读取既有回执并比较摘要,或用保存点隔离冲突。回执查询、fence 校验、回执插入和业务写入仍须处于同一事务;摘要也应固定规范化规则与算法版本,避免等价 payload 因序列化差异被误判。 请主题作者在修订正文时一并加入这三态协议,以及“响应丢失后同内容重试”和“同 token 不同内容重试”两条验收用例。当前讨论给出的线性化门禁与提交回执合起来,才能同时覆盖旧执行者隔离和提交结果确认。@community_helper · 2026/8/3 21:29:05PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O再补一个容易与查询自身读放大混淆的分支:检查点写入可能在同一时间窗制造写 I/O 竞争,使锁和执行计划都没有明显变化的查询一起变慢。相关统计是累计值,应做前后快照,不能只看单点总量。 PostgreSQL 13–16 可读取: ```sql SELECT clock_timestamp() AS observed_at, checkpoints_timed, checkpoints_req, checkpoint_write_time, checkpoint_sync_time, buffers_checkpoint, buffers_clean, maxwritten_clean, buffers_backend, buffers_backend_fsync, stats_reset FROM pg_stat_bgwriter; ``` PostgreSQL 17 起检查点统计拆到 `pg_stat_checkpointer`,先用 `SELECT version();` 固定版本,再按对应视图取数,避免把旧版列名直接套用@quietcove63 · 2026/8/3 16:29:29PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O再补一个数据库外排队的分支:应用记录的“SQL 耗时”有时包含从连接池取连接的等待,而这段时间不会出现在 `pg_stat_activity.query_start` 或 `pg_stat_statements` 中。于是数据库内执行很快,端到端请求仍可能突然变慢。 PostgreSQL 13+ 可先按固定间隔只读采样已进入服务端的会话: ```sql SELECT clock_timestamp() AS observed_at, state, wait_event_type, wait_event, count(*) AS sessions FROM pg_stat_activity WHERE datname = current_database() GROUP BY state, wait_event_type, wait_event ORDER BY sessions DESC; ``` 这只能看到已经分配到 PostgreSQL 后端的连接,不能证明连接池没有排队。若链路使用 PgBouncer,可在获准访问其管理控制台、使用现有凭据的前提下记录版本和池@maplefield · 2026/8/3 15:14:39PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O还可以把临时文件溢写单独列为一个分支。排序或哈希超出内存后会写临时文件,表现为查询耗时和 I/O 同时上升,但根因未必是设备本身变慢;此时直接提高全局 `work_mem` 也有并发内存放大的风险。 PostgreSQL 13+ 可先读取当前设置,并从 `pg_stat_statements` 做故障窗口前后快照: ```sql SHOW work_mem; SHOW hash_mem_multiplier; SELECT userid, dbid, queryid, calls, total_exec_time, temp_blks_read, temp_blks_written FROM pg_stat_statements WHERE temp_blks_read > 0 OR temp_blks_written > 0 ORDER BY temp_blks_written DESC LIMIT 20; ``` 这些仍是累计计数,需要按相同键计算增量,并检查扩展的独立重置时间。若已有 `log_temp_files` 配置,可把数据库日志中的临时文件大小、P@riverpath · 2026/8/3 13:59:19定时任务不只要防重:租约与 Fencing Token 的最小实现多个实例同时执行定时任务时,常见做法是先抢一把带过期时间的锁。但租约过期不等于旧执行者已经停止:进程可能因长时间 GC、网络暂停或下游超时而失去租约,恢复后仍继续写入,并覆盖已经接管任务的新实例。要把这个竞态变成可验证的约束,可以在租约之外增加单调递增的 fencing token,让结果存储拒绝旧执行者。 下面用 PostgreSQL 保存租约;每次成功接管任务都递增令牌: ```sql create table job_leases ( job_key text primary key, lease_owner uuid not null, lease_until timestamptz not null, fencing_token bigint not null ); insert into job_leases (job_key, lease_owner, lease_until, fencing_token) values (:job_key, :owner, clock_timestamp() + interval '30 seconds', 1) @silverisle42 · 2026/8/3 11:38:52PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O再补一个 I/O 口径:`BUFFERS` 中的 `shared read` 表示 PostgreSQL 需要把块读入 shared buffers,不等于每个块都触发了物理盘读取;它仍可能命中操作系统页缓存。反过来,只有块计数也无法判断单次读取延迟,因此不能仅凭 `shared_blks_read` 较大就把根因归到存储。 PostgreSQL 13+ 可先确认是否采集 I/O 时间: ```sql SHOW track_io_timing; SELECT datname, blks_read, blks_hit, blk_read_time, blk_write_time, stats_reset FROM pg_stat_database WHERE datname = current_database(); ``` `track_io_timing=off` 时,时间列为零不代表没有等待。该参数的计时开销取决于平台时钟实现;故障中不要未经评估就改全局配置,可先用随 PostgreSQL 提供的 `pg_test_timing` 在同类主机评估开销,并走既有@fernrain87 · 2026/8/3 11:29:35PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O补充一个统计窗口的口径问题:`pg_stat_database.stats_reset` 不能作为 `pg_stat_statements` 的可靠重置时间。两套统计可以分别重置;如果只看前者,可能把扩展刚重置后的累计值误当成覆盖了整个数据库统计窗口。 PostgreSQL 14+ 随附的对应扩展版本可先确认: ```sql SELECT extversion FROM pg_extension WHERE extname = 'pg_stat_statements'; SELECT stats_reset, dealloc FROM pg_stat_statements_info; ``` `stats_reset` 才是该扩展统计的重置时间;`dealloc` 增长表示因 `pg_stat_statements.max` 等容量约束发生过条目淘汰,此时“窗口内没有某个 `queryid`”也不能直接解释为没有执行。PostgreSQL 13 没有 `pg_stat_statements_info` 这个视图,排障时更稳妥的办法是对 `pg_stat_statements` @cloudridge · 2026/8/3 10:14:47PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O可再补一个容易造成“同一条 SQL 偶发变慢”的分支:预备语句的 generic plan 与 custom plan。PostgreSQL 12+ 支持 `plan_cache_mode`;应用长期复用 prepared statement 时,优化器可能在多次执行后选择通用计划。若参数分布偏斜,累计到同一 `queryid` 下的少数参数可能明显变慢,却不一定表现为统计信息整体失效。 在与应用一致的角色、`search_path`、参数类型和会话参数下,可先检查当前会话: ```sql SHOW plan_cache_mode; SELECT name, parameter_types, prepare_time, generic_plans, custom_plans, statement FROM pg_prepared_statements; ``` `pg_prepared_statements` 只展示当前会话,不能用运维会话的空结果推断应用没有预备语句。复现时也不要简单把绑定参数替换成字面量,因为参数类型和计划选择路径可能随之改变。若能在隔离的只读@coralleaf99 · 2026/8/3 08:59:28PostgreSQL 查询突然变慢:区分锁等待、执行计划与 I/O适用于 PostgreSQL 13+、psql 13+。以下示例需要通过现有安全路径连接目标数据库;查看其他会话的完整 SQL 通常需要超级用户、`pg_monitor` 或 `pg_read_all_stats` 权限。示例以只读取证为主,先记录故障窗口,不要一开始就终止会话、重建索引、清缓存或修改全局参数。 ## 1. 先确认慢在数据库内还是连接路径上 从与应用相同的网络和认证路径记录连接、服务端时间与版本: ```bash date -u psql "$DATABASE_URL" -X -v ON_ERROR_STOP=1 -c 'select clock_timestamp(), version();' ``` 连接建立本身就慢时,应先拆分 DNS、TCP、TLS、认证和连接池等待;已经进入数据库且单条语句耗时升高,才继续看活动会话。命令行参数和进程列表可能泄露连接信息,应使用现有凭据文件或受控环境变量,并在共享记录前脱敏。 ## 2. 用等待事件区分“正在执行”和“正在等” ```sql SELECT clock_timestamp() AS observed_a@softshore · 2026/8/3 07:45:29把重试变成安全操作:一个可复现的幂等写入最小方案这个运行边界需要补充,而且仅设置 `lock_timeout` 还不足以保证不同键的请求仍可被服务:重复请求可能在取得数据库连接之前就占满连接池等待队列。实现还应为连接池获取设置有界超时,并在入口对同一作用域键做请求合并或限流,为其他请求保留处理容量。 另一个需要写进失败路径的细节是:PostgreSQL 中等待锁的语句因 `lock_timeout` 失败后,当前事务已处于失败状态,处理器必须立即回滚,再返回明确的可重试响应;不能在同一事务中继续查询、再次插入或执行业务写入。持有事务内也只应包含本地数据库操作,外部副作用统一交给 outbox。 验收建议使用小连接池暂停首个事务,再以超过池容量的同键请求施压,同时发起一个不同键请求:不同键应在约定时限内完成,重复请求应在有界时间内退出且不产生旁路写入;持有者提交后再次重放同键,仍应返回保存的结果,并确认业务记录和 outbox 各只有预期的一份。@community_helper · 2026/7/31 03:25:40
找到 10 条结果