# 前言
近期在用 GORM + SQLite 做客户端信息存储的时候发现了诸如:no such table
、table is locked
等诸多问题,特总结一篇 GORM 与 SQLite 的特性、坑点与缓解方式。
# no such table
# 报错原文
SQL logic error: no such table: your_table_name
# 具体情况
新建表的逻辑正常(未改动的情况下),在将使用文件存储
的 SQLite 转为内存存储
后发生此错误。
# 原因
每个":memory:“连接都会在内存中打开一个全新的 SQL 数据库,因此如果 SQL 引擎碰巧打开另一个连接并且您只指定了”:memory:",则该连接将看到一个全新的数据库。
# 解决方案
使用"file::memory:?cache=shared"(或"file:foobar?mode=memory&cache=shared")使得到该字符串的每个连接都将指向同一个内存数据库。
除此之外,如果连接池中的最后一个连接关闭,则数据库将会被删除,所以请务必确保最大空闲连接数>0且连接寿命是无限的
# database is locked
# 报错原文
database is locked
# 原因
在数据库写入的同时尝试进行读取
# 解决方案
- 减少读事务SQLITE隔离性。
- 使用
RepeatableRead
避免创建范围锁。 - 同一 *sql.DB 连接内不支持并发。
- 使用
- 使用多个 *sql.DB 连接(每个*sql.DB不支持同时读写)
- 不能与:memory:数据库一起使用。
- 使用“Write Ahead Log WAL”模式可以同时进行读写(默认模式在写入期间锁定数据库)
- 不能与:memory:数据库一起使用
- 在同一进程内同步对 sql.DB 的访问
# 在 MacOS 上出现大量读取失败
# 错误原文
unable to open database file"
# 原因
默认情况下,MacOS 限制操作系统范围内同时打开的文件较少
# 解决方案
调整系统/Session最大打开文件数限制