解决Access批量插入时的“文件共享锁计数超出”问题(无法修改MaxLocksPerFile默认值)
解决Access批量插入时的“文件共享锁计数超出”问题(无法修改MaxLocksPerFile默认值)
我完全懂你这种被公司配置卡脖子的无奈——没法改MaxLocksPerFile默认值,还要硬着头皮搞定150万行数据插入Access,换谁都头疼!结合你的代码和遇到的问题,我给你几个实打实的调整思路,应该能绕开这个锁计数的坑:
1. 把事务拆到最小,强制释放锁
你当前是每100个chunk才提交一次事务,这意味着50万行数据才会触发一次提交,Access的锁会在事务中不断累积,很容易触发上限。建议把提交频率拉到最高,每个chunk插入后立刻提交,并且给Access留足够时间释放锁,甚至可以重置游标来清空累积的锁:
修改你代码里的循环逻辑:
for idx, chunk in enumerate(chunks): # ... 保存chunk到临时文件的代码不变 ... try: start_time = time.time() cursor.execute(sql) # 每个chunk插入后立即提交,不要攒到100个 conn.commit() time.sleep(2) # 延长等待时间,给Access足够时间释放锁 # 可选:重置游标,避免游标累积锁资源 cursor.close() cursor = conn.cursor() elapsed_time = time.time() - start_time print(f"Bulk insert for chunk {idx} completed in {elapsed_time:.2f} seconds") except pyodbc.Error as e: print(f"Error during bulk insert for chunk {idx}: {e}") conn.rollback()
2. 改用Access原生导入工具(绕开pyodbc的锁问题)
pyodbc的SQL插入方式对Access的锁管理不够友好,不如直接调用Access自带的DoCmd.TransferText功能——这是Access原生的导入工具,它对锁的处理更高效,甚至不用拆分文件就能直接导入百万级数据。你可以用pywin32库调用Access的COM接口实现:
import win32com.client import os def import_txt_to_access(txt_path, db_path, table_name): # 确保数据库路径存在 if not os.path.exists(db_path): print(f"Database {db_path} not found!") return try: # 启动Access并打开数据库 access_app = win32com.client.Dispatch("Access.Application") access_app.OpenCurrentDatabase(db_path) # 调用原生TransferText导入制表符分隔的txt access_app.DoCmd.TransferText( TransferType=0, # 0代表acImportDelim(导入分隔文件) TableName=table_name, FileName=txt_path, HasFieldNames=False, # 根据你的txt是否有表头调整为True/False Delimiter="\t" ) print("导入完成!") access_app.Quit() except Exception as e: print(f"导入出错:{e}") access_app.Quit() # 调用示例 import_txt_to_access("你的数据文件.txt", "目标Access数据库.accdb", "目标表名")
这种方法让Access自己处理整个导入流程,它的原生逻辑会更合理地分配锁资源,大概率能避开锁计数超限的问题。
3. 优化临时文件的处理时机
你当前是所有chunk导入完成后才删除临时文件,这些文件可能会被Access一直持有引用,累积锁资源。建议每个chunk导入完成后立即删除临时文件,同时确保Access已经释放了对文件的引用:
修改代码里的临时文件删除逻辑:
try: cursor.execute(sql) conn.commit() time.sleep(1) # 导入完成后立刻删除临时文件,释放Access的文件引用 if os.path.exists(chunk_file_path): os.remove(chunk_file_path) print(f"Temporary file {chunk_file_path} deleted") except pyodbc.Error as e: print(f"Error during bulk insert for chunk {idx}: {e}") conn.rollback()
这样就不用等到最后才清理,减少Access同时持有的文件引用数量。
4. 申请调整Access的记录锁定设置(如果可行)
如果公司允许的话,让管理员打开目标Access数据库,调整一下锁定设置:
- 打开数据库后,点击「文件」→「选项」→「客户端设置」
- 在「高级」区域,把「默认记录锁定」改成「不锁定」,或者把「编辑记录时锁定记录」改成「编辑记录时锁定页」
这个设置能减少Access在插入数据时的锁占用,从根源上缓解锁计数超限的问题。
备注:内容来源于stack exchange,提问作者user28814433
相关产品推荐
相关产品推荐

