sqlitex

package
v0.10.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package sqlitex 在 glebarez/sqlite 之上补一条 database/sql 不会替你做的事: **事务结束后保证连接是干净的**。

为什么需要它(这是线上整库锁死的直接原因):

  • SQLite 的回滚日志模式(journal_mode=delete)下,COMMIT 需要 EXCLUSIVE 锁; 只要有别的连接持着 SHARED(一次普通查询就算),它就得等,等不到 busy_timeout 就返回 SQLITE_BUSY。**而 SQLite 的语义是:COMMIT 返回 BUSY 时 事务并没有结束,仍然活着**(可以重试 COMMIT 或 ROLLBACK)。
  • Go 的 database/sql 在 Tx.Commit 出错时只做一件事:把连接放回池子。 它既不会调用 driver.Tx.Rollback,也不会因为 BUSY 丢弃连接 (见 GOROOT/src/database/sql/sql.go 的 Tx.Commit → tx.close(err) → putConn(err):只有 err == driver.ErrBadConn 才会 Close,其余一律回池)。
  • 于是那条连接带着一个**没结束的写事务**回到空闲池:RESERVED/PENDING 锁永远 不放。之后所有读都等满 busy_timeout 报 SQLITE_BUSY,所有写在拿锁时失败, 在这条连接上 Begin 直接报 "cannot start a transaction within a transaction (1)"——整库死锁,直到进程重启(重启时 SQLite 用残留的 -journal 回滚)。

这个包做的事只有两件:

  1. COMMIT 失败时**自己把事务回滚掉**(先驱动 Rollback,再退回 SQL ROLLBACK)。
  2. 回滚不掉时返回 driver.ErrBadConn,让 database/sql 丢弃这条连接(进程内关闭 文件描述符、释放 fcntl 锁)——宁可换一条新连接,也不把脏连接放回池子。

用 DriverName + sqlite.Dialector{DriverName: sqlitex.DriverName} 启用,见 models.Init。

Index

Constants

View Source
const DriverName = "sqlite-guarded"

DriverName 是受保护驱动的注册名。

与 glebarez 自带的 "sqlite" 并存:测试与迁移脚本里直接用 "sqlite" 仍然可用, 只有服务自己的连接池走这一条。

Variables

This section is empty.

Functions

func Register

func Register()

Register 注册受保护驱动。可重复调用。

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL