Skip to content

fix(database):并发写入资产时 SQLite 锁竞争导致 database is locked - #247

Open
zabcxky-123 wants to merge 1 commit into
Ed1s0nZ:mainfrom
zabcxky-123:fix/sqlite-concurrent-asset-writes
Open

fix(database):并发写入资产时 SQLite 锁竞争导致 database is locked#247
zabcxky-123 wants to merge 1 commit into
Ed1s0nZ:mainfrom
zabcxky-123:fix/sqlite-concurrent-asset-writes

Conversation

@zabcxky-123

@zabcxky-123 zabcxky-123 commented Aug 12, 2026

Copy link
Copy Markdown

并发调用 create_asset 时报错“更新资产失败: database is locked”。根因是 UpsertAssets 使用延迟事务:多个写入者先 SELECT 去重键、再升级写锁,同时升级时互相竞争。
修复:
SQLite DSN 增加 _txlock=immediate,所有事务以 BEGIN IMMEDIATE 启动,在事务开始时就获取写锁;
DB 层新增写事务互斥(serialTx 包装),进程内写事务严格串行,提交/回滚后释放互斥锁,彻底消除进程内 SQLITE_BUSY。
改动仅限数据库事务层与一个并发回归测试,无其他变更。
验证:
无修复时:TestUpsertAssetsConcurrentCreatesDoNotLock 失败(创建资产失败: database is locked)
修复后:回归测试通过,go test ./... 全部通过
go test -race ./internal/database 通过
改动文件:
internal/database/database.go
internal/database/asset_test.go
internal/database/rbac.go
internal/database/vulnerability.go

并发调用 create_asset 时报错“更新资产失败: database is locked”。根因是 UpsertAssets 使用延迟事务:多个写入者先 SELECT 去重键、再升级写锁,同时升级时互相竞争。

修复(两层防护):
1. SQLite DSN 增加 _txlock=immediate,所有事务以 BEGIN IMMEDIATE 启动,在事务开始时就获取写锁;
2. DB 层新增写事务互斥(serialTx 包装),进程内写事务严格串行,提交/回滚后释放互斥锁,彻底消除进程内 SQLITE_BUSY。

改动仅限数据库事务层与一个并发回归测试,无其他变更。

验证:
- 无修复时:TestUpsertAssetsConcurrentCreatesDoNotLock 失败(创建资产失败: database is locked)
- 修复后:回归测试通过(10 轮),go test ./... 全部通过
- go test -race ./internal/database 通过
@zabcxky-123
zabcxky-123 force-pushed the fix/sqlite-concurrent-asset-writes branch from efa76ed to a5c911d Compare August 12, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant