fix: 写库并发控制(advisory锁串行写+分批提交+lock_timeout+死锁重试), refresh_pending写任务加重试

死锁根因:sds-refresh-pending 与 label-ocr 整点并发写同一分区 Orders_2026_08,
互等对方未提交事务(ShareLock)。24h 内同类死锁 7 起。
- sync_orders_and_goods 所有写事务先取同一把 PG advisory 锁(事务级),单锁无环,死锁结构性消除
- 同步按批(1000单)独立提交,持锁窗口从整个 pending 集缩到单批
- 连接预设 lock_timeout=15s,DeadlockDetected/LockNotAvailable 整事务重试 3 次(退避1/3/7s)
- label-ocr 的 update_ocr_batch/update_ocr_fields 走同一把锁+重试
- sds/riin refresh_pending 的 upsert_records 加任务级重试(retries=3)
This commit is contained in:
yeuimu
2026-09-02 03:23:02 +00:00
parent d6be75d6b7
commit c545c1b87d
5 changed files with 103 additions and 35 deletions
+1
View File
@@ -124,6 +124,7 @@ inkreach-prefect/
- `mappers.py`:RIIN/SDS 原始订单 → 统一 `OrderUpsertInput` / `GoodsUpsertInput`,含状态/平台/快递来源/国家归一映射。
- `db.py`:`SyncDB.sync_orders_and_goods()` —— Orders/Goods 批量 `ON CONFLICT` upsert,**写入前用库中已有 `createdAt` 覆盖**(保证幂等),Goods 写前删除该订单不再出现的行;另有 `get_latest_ordered_at` / `get_pending_orders` / `get_order_count_by_status` / `get_local_order_nos` / `get_local_goods_count` / `get_orders_with_100_prefix` 等查询。
- **写并发控制**(2026-08 死锁修复):所有写 Orders/Goods 的事务(同步 flow 与 label-ocr 的 OCR 回写)先取同一把 PG advisory 锁(`DB_WRITE_LOCK_KEY`,事务级,commit/rollback 即释放)串行化——单锁无环,写事务之间结构性无死锁;`sync_orders_and_goods` 按批(`ORDER_CHUNK`=1000)独立提交,持锁窗口从"整个 pending 集"缩到"单批";连接预设 `lock_timeout=15s`;对 `DeadlockDetected` / `LockNotAvailable` 整事务自动重试 3 次(退避 1/3/7s),另有 flow/task 级 retries 兜底。
- `clients.py`:客户端工厂(读 Secret Block)、`fetch_riin/sds_all_pages`(顺序分页,页间 500ms,仅对 5xx/429/超时重试)、RIIN 商品并发拉取(并发 20)、SDS 物流渠道字典(24h 缓存)。
### 关键差异点