@@ -72,9 +72,14 @@ func NewLogStorage(path string) (*LogStorage, error) {
7272 return ls , nil
7373}
7474
75+ // logSQLiteDSN WAL + busy_timeout,避免與其它連接短暫競爭時出現 database is locked
76+ func logSQLiteDSN (path string ) string {
77+ return path + "?_journal_mode=WAL&_synchronous=NORMAL&_busy_timeout=15000"
78+ }
79+
7580// openLogStorageDB 打开數據库,若完整性检查失败则备份並重建
7681func openLogStorageDB (path string ) (* sql.DB , * LogStorage , error ) {
77- dsn := path + "?_journal_mode=WAL&_synchronous=NORMAL"
82+ dsn := logSQLiteDSN ( path )
7883 db , err := sql .Open ("sqlite3" , dsn )
7984 if err != nil {
8085 return nil , nil , fmt .Errorf ("打开日志數據库失败: %w" , err )
@@ -278,13 +283,43 @@ func (ls *LogStorage) processLogs() {
278283 }
279284}
280285
281- // batchInsert 批量插入日志
286+ func sqliteLogLockedRetryable (err error ) bool {
287+ if err == nil {
288+ return false
289+ }
290+ msg := strings .ToLower (err .Error ())
291+ return strings .Contains (msg , "database is locked" ) || strings .Contains (msg , "locked" ) ||
292+ strings .Contains (msg , "busy" )
293+ }
294+
295+ // batchInsert 批量插入日志(對 SQLITE_BUSY / locked 短重試,配合 DSN busy_timeout)
282296func (ls * LogStorage ) batchInsert (entries []* logEntry ) error {
283297 if len (entries ) == 0 {
284298 return nil
285299 }
300+ const maxAttempts = 6
301+ var lastErr error
302+ for attempt := 0 ; attempt < maxAttempts ; attempt ++ {
303+ if attempt > 0 {
304+ time .Sleep (time .Duration (20 + attempt * 25 ) * time .Millisecond )
305+ }
306+ lastErr = ls .batchInsertOnce (entries )
307+ if lastErr == nil {
308+ return nil
309+ }
310+ if ! sqliteLogLockedRetryable (lastErr ) {
311+ return lastErr
312+ }
313+ }
314+ return lastErr
315+ }
316+
317+ // batchInsertOnce 單次事務批量插入
318+ func (ls * LogStorage ) batchInsertOnce (entries []* logEntry ) error {
319+ if len (entries ) == 0 {
320+ return nil
321+ }
286322
287- // 使用事務批量插入
288323 tx , err := ls .db .Begin ()
289324 if err != nil {
290325 return err
@@ -307,7 +342,6 @@ func (ls *LogStorage) batchInsert(entries []*logEntry) error {
307342 return err
308343 }
309344
310- // 獲取插入的 ID
311345 id , _ := result .LastInsertId ()
312346 insertedLogs = append (insertedLogs , & LogRecord {
313347 ID : id ,
@@ -322,7 +356,6 @@ func (ls *LogStorage) batchInsert(entries []*logEntry) error {
322356 return err
323357 }
324358
325- // 通知所有订阅者
326359 ls .notifySubscribers (insertedLogs )
327360
328361 return nil
0 commit comments