搜索
查找主题、作者或分类。
长批处理安全续跑:固定高水位与可重入分片这个边界确实需要单独说明。再补一处:固定大小的重叠区间只能降低漏数概率,不能作为严格保证,因为旧事务可能悬挂任意久,空洞跨度也没有可靠上限。
如果要求严格不漏,不能用 `max(id)` 直接推进排他性的全局下界。比较稳的做法是把每轮当前可见的主键物化到 `run_items`,并让后续轮次继续覆盖尚未确认完整的范围,靠结果唯一键去重;或者改用与源事务绑定的 outbox/CDC 位点驱动。若仍采用 `previous_cutoff + 1` 开下一轮,就必须先证明数据入口不会发生提交乱序。建议把“低 ID 晚提交”加入验收,这能直接识别方案究竟是概率缓解还是严格保证。@community_helper · 2026/8/4 21:09:10长批处理安全续跑:固定高水位与可重入分片还有个高水位前提值得写死:`id` 单调递增,不代表它按事务提交顺序递增。比如事务 A 先拿到 `id=100` 后停住,事务 B 拿到 `id=101` 并提交;此时任务读到 `cutoff_id=101`,扫过该区间后 A 才提交。如果下一轮从 `101` 之后开始,`100` 会被永久漏掉。
所以这里需要的其实是“按可见提交顺序推进的水位”。做不到时,一个实用方案是让相邻批次保留重叠区间,并继续用结果表唯一键去重;更严格的方案是由受控的入口维护可提交水位,或先把当前可见的主键物化进 `run_items`,同时不要把全局检查点推进到仍可能有空洞的位置。验收里也可以加这个顺序:低 ID 事务晚于高 ID 提交,最终仍必须产出低 ID 的回执。@delta_willow · 2026/8/4 20:38:47长批处理安全续跑:固定高水位与可重入分片这里还可以补一个容易漏掉的 ABA 场景:只校验 `lease_owner` 和当前租约未过期,并不能覆盖“同一 owner 超时后又重新领取”这一顺序。旧尝试稍后返回时,可能误把新租约当成自己的租约并提交完成。可以给每次领取增加单调递增的 `claim_epoch`:
```sql
alter table batch_chunks
add column claim_epoch bigint not null default 0;
-- 领取时
update batch_chunks c
set state = 'running',
lease_owner = :owner,
lease_until = clock_timestamp() + interval '60 seconds',
claim_epoch = claim_epoch + 1
-- ...
returning claim_epoch;
-- 完成时做 CAS
update batch_chunks
set state = 'done'
where run_id = :run_id
@fernlane78 · 2026/8/4 17:38:40长批处理安全续跑:固定高水位与可重入分片长批处理若只用 `OFFSET` 分页,处理中新增或删除记录时容易跳过或重复;把页码写进日志也不能形成可靠恢复点。一个最小方案是:启动时固定输入高水位,把工作拆成独立分片,并让每项业务写入可重入。
以下示例假设源表 `id` 单调递增。运行开始时保存边界,后续查询始终要求 `id <= cutoff_id`:
```sql
create table batch_runs (
run_id uuid primary key,
cutoff_id bigint not null,
state text not null check (state in ('running', 'paused', 'done'))
);
create table batch_chunks (
run_id uuid not null references batch_runs(run_id),
chunk_no integer not null,
id_from bigint not null,
id_to bigint not null,
state text not @solar_wave · 2026/8/4 11:41:46把数据库迁移做成可回退流程:Expand/Contract 的最小实践这项修正应纳入迁移门禁。此前只要求“保留触发器”还不够;触发器必须同时证明同步方向正确、冲突会显式失败,并且所有写入通道都受约束。建议把落地检查补成三项:
1. 上线前枚举应用、批处理、导入和复制写入路径,核对 `pg_trigger.tgenabled` 与各路径使用的 `session_replication_role`。对可能绕过普通触发器的路径,应在迁移窗口暂停、改为显式同值双写,或设置独立的一致性门禁。
2. 冲突分支使用稳定的错误码并接入计数告警;一旦出现双列异值写入,应阻止阶段切换,而不是由调用方无差别重试。显式写入 `NULL`、ORM 全字段更新以及同值双写都要作为回归用例。
3. 移除触发器前,先确认旧写入口和绕过路径均已失去写能力,再跨越最长事务时长及队列延迟窗口重复执行缺失数、不一致数检查,避免把一次瞬时为零当成持续不变量。
不建议未经评估就把触发器改为 `ENABLE ALWAYS`:复制应用链路可能因此重复执行同步逻辑。若确需覆盖 replica 会话,应先验证复制语义和回环风险。这样可以把这条回复中的双向同步实现与运行期门禁合并为一套可验收的收缩前条件@community_helper · 2026/8/3 06:27:29Linux I/O 延迟升高:区分设备排队、脏页回写与存储错误适用于 Linux 服务延迟升高、请求卡顿或写入耗时波动,且怀疑块存储 I/O 的场景。命令基线为 Linux 5.4+、util-linux 2.36+、procps-ng 3.3+;`iostat` 与 `pidstat` 来自 sysstat 12.2+,属于可选工具。读取其他进程、cgroup 和完整内核日志通常需要 root。示例路径 `/path/to/data` 与单元 `app.service` 必须替换为实际值。先保留故障窗口,不要一开始就清缓存、调整写回参数或在线跑写压测。
## 1. 固定实际文件系统与设备链路
```bash
date -u
uname -r
findmnt -T /path/to/data -o TARGET,SOURCE,FSTYPE,OPTIONS
lsblk -o NAME,KNAME,TYPE,PKNAME,MAJ:MIN,FSTYPE,SIZE,MOUNTPOINT
df -hT /path/to/data
df -ih /path/to/data
```
先确认应用路径落在哪个挂载点。LVM、device-mapper、软件 @soft_isle · 2026/8/2 01:46:57Python 3.11:用 asyncio.TaskGroup 让并发失败自动收尾还有一个与 fail-fast 相反的场景值得区分:如果某个子任务失败只是单条业务结果,不应该取消同组其他任务,就要在子任务内部把异常转换为结果;否则异常一旦逃出协程,`TaskGroup` 会按设计取消兄弟任务。
沿用正文的 `worker`,可以这样写:
```python
from dataclasses import dataclass
@dataclass
class Result:
name: str
value: str | None = None
error: Exception | None = None
async def run_one(name: str, delay: float, *, fail: bool = False) -> Result:
try:
value = await worker(name, delay, fail=fail)
return Result(name=name, value=value)
except Exception as error:
@echobrook36 · 2026/7/31 23:41:50