From 9c3cc38a44947327390a8d1ea0ccb039d27c4464 Mon Sep 17 00:00:00 2001 From: Misaka_Company Date: Wed, 15 Jul 2026 09:42:17 +0800 Subject: [PATCH] fix(sync): retry cleanup on Access -1102 lock contention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ACE ODBC reports lock contention ("无法更新;当前被锁定。(-1102)") as a generic pyodbc.Error (HY000), NOT pyodbc.OperationalError, so the old except clause never caught it and gave up after the first collision — making cleanup_lock_retries:3 a no-op for the 氩弧焊/高写入库 -1102 case. Now catch pyodbc.Error and retry only on lock messages ("被锁定"/"-1102"), re-raising other errors immediately instead of retrying them 3×. --- src/sync/access_reader.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/sync/access_reader.py b/src/sync/access_reader.py index 5e3b294..3189f32 100644 --- a/src/sync/access_reader.py +++ b/src/sync/access_reader.py @@ -111,8 +111,16 @@ class AccessReader: ) total += cur.rowcount break - except pyodbc.OperationalError: - if attempt < retries - 1: + except pyodbc.Error as e: + # ACE ODBC reports lock contention ("无法更新;当前被锁定。 + # (-1102)") as a generic ``pyodbc.Error`` (HY000), NOT as + # ``pyodbc.OperationalError`` — so the old handler silently + # missed it and gave up after the first collision. Retry only + # on lock messages; re-raise anything else so genuine errors + # surface immediately instead of being retried 3×. + msg = str(e) + is_lock = "被锁定" in msg or "-1102" in msg + if is_lock and attempt < retries - 1: time.sleep(0.2 * (attempt + 1)) else: raise