当前位置: 首页 > news >正文

golang使用sqlite3,开启wal模式,并发读写

因为sqlite是基于文件的,所以默认情况下,sqlite是不支持并发读写的,即写操作会阻塞其他操作,同时sqlite也很容易就产生死锁。

但是作为一个使用广泛的离线数据库,从sqlite3.7.0版本开始(SQLite Release 3.7.0 On 2010-07-21),sqlite引入了更常见的WAL机制来解决页面的读写并发问题。但是sqlite的实现特点决定了其并发能力较低。

SELECT sqlite_version();
3.8.8

开启了WAL模式之后,sqlite就会生成三个文件test.db, test.db-shm, test.db-wal。在WAL模式下支持一写多读。

当临时文件的内容达到一定的量,sqlite会进行一次落盘。

PRAGMA wal_autocheckpoint=5000;

pagesize默认设置的是4k,autocheckpoint设置5000,表示5000个page的数据量,会进行一下checkpoint,也就是20M。

查询日志模式:PRAGMA journal_mode;

设置日志模式:PRAGMA journal_mode=WAL;

示例
CREATE TABLE "users" (
"id"  INTEGER,
"name"  TEXT,
"age"  INTEGER,
"created_at"  TEXT,
"updated_at"  TEXT
);

使用Go的gorm来操作sqlite3

package go_sqliteimport ("fmt""strconv""sync""time""database/sql""gorm.io/driver/sqlite""gorm.io/gorm"
)var dbfile = "demos/go_sqlite/test.db"func Run() {gormDB, sqlDB, err := InitDB()if err != nil {panic(err)}defer sqlDB.Close()users := []User{}for i := 0; i < 1000; i++ {user := User{Name:      "user_" + strconv.Itoa(i),Age:       uint8(i % 100),CreatedAt: time.Now().Unix(),UpdatedAt: time.Now().Unix(),}users = append(users, user)}err = BatchInsertUsers(gormDB, users)if err != nil {panic(err)}users, err = GetUsers(gormDB)if err != nil {panic(err)}fmt.Println(len(users))fmt.Println(users[0])
}type User struct {ID        uintName      stringAge       uint8CreatedAt int64UpdatedAt int64
}func InitDB() (*gorm.DB, *sql.DB, error) {gormDB, err := gorm.Open(sqlite.Open(dbfile), &gorm.Config{})if err != nil {return nil, nil, err}sqlDB, _ := gormDB.DB()gormDB.Exec("PRAGMA journal_mode=WAL;")sqlDB.SetMaxIdleConns(10)sqlDB.SetMaxOpenConns(100)sqlDB.SetConnMaxLifetime(time.Hour)return gormDB, sqlDB, nil
}func BatchInsertUsers(gormDB *gorm.DB, users []User) error {batchSize := 100batchCount := (len(users) + batchSize - 1) / batchSizefor i := 0; i < batchCount; i++ {start := i * batchSizeend := (i + 1) * batchSizeif end > len(users) {end = len(users)}batch := users[start:end]tx := gormDB.Begin()if err := tx.Error; err != nil {return err}if err := tx.Create(&batch).Error; err != nil {tx.Rollback()return err}if err := tx.Commit().Error; err != nil {return err}}return nil
}func GetUsers(gormDB *gorm.DB) ([]User, error) {var users []Usererr := gormDB.Find(&users).Errorif err != nil {return nil, err}return users, nil
}

并发测试

var wg sync.WaitGroupfunc Run2() {gormDB, err := gorm.Open(sqlite.Open(dbfile), &gorm.Config{})if err != nil {panic("failed to connect database")}gormDB.Exec("PRAGMA journal_mode=WAL;")sqlDB, _ := gormDB.DB()sqlDB.SetMaxIdleConns(10)sqlDB.SetMaxOpenConns(100)wg.Add(2000)// 并发写入 1000 条数据for i := 0; i < 1000; i++ {go func(i int) {defer wg.Done()err := gormDB.Transaction(func(tx *gorm.DB) error {user := User{Name: fmt.Sprintf("user_%d", i)}result := tx.Create(&user)return result.Error})if err != nil {fmt.Printf("failed to write data: %v\n", err)}}(i)}// 并发读取数据for i := 0; i < 1000; i++ {go func() {defer wg.Done()var users []Usererr := gormDB.Transaction(func(tx *gorm.DB) error {result := tx.Find(&users)return result.Error})if err != nil {fmt.Printf("failed to read data: %v\n", err)} else {fmt.Printf("read %d records\n", len(users))}}()}wg.Wait()fmt.Println("done")
}
参考

https://mp.weixin.qq.com/s/9Y1EfzM5cups9oklByAW5Q

https://mp.weixin.qq.com/s/4AhMBJaZ4NZqfqcoPduXjg

http://www.lryc.cn/news/533823.html

相关文章:

  • 如何利用maven更优雅的打包
  • 音频进阶学习十二——Z变换一(Z变换、收敛域、性质与定理)
  • cursor指令工具
  • MySQL 主从读写分离实现方案(一)—MariaDB MaxScale实现mysql8读写分离
  • 阿里云 | DeepSeek人工智能大模型安装部署
  • LLAMA-Factory安装教程(解决报错cannot allocate memory in static TLS block的问题)
  • STM32 CUBE Can调试
  • MySQL数据存储- 索引组织表
  • 基于STM32设计的仓库环境监测与预警系统
  • VSCode便捷开发
  • 理解 Maven 的 pom.xml 文件
  • docker数据持久化的意义
  • opentelemetry-collector 配置elasticsearch
  • ASP.NET Core JWT Version
  • 【ArcGIS】R语言空间分析、模拟预测与可视化技术
  • 日常知识点之面试后反思遗留问题汇总
  • 链表(LinkedList) 1
  • Qt:Qt Creator项目创建
  • windows11上,使用pipx安装Poetry,Poetry的安装路径是什么?
  • 详解状态模式
  • 能否通过蓝牙建立TCP/IP连接来传输数据
  • uniapp mqttjs 小程序开发
  • 爬虫工程师分享:获取京东商品详情SKU数据的技术难点与攻破方法
  • 数据库操作与数据管理——Rust 与 SQLite 的集成
  • LeetCode 0063.不同路径 II:动态规划 - 原地使用地图数组,几乎无额外空间开销
  • elementui:el-table支持搜索、切换分页多选功能,以及数据回显
  • 深度整理总结MySQL——索引正确使用姿势
  • 使用LLaMA Factory踩坑记录
  • 亚博microros小车-原生ubuntu支持系列:25 二维码控制运动
  • 基于深度学习的人工智能量化衰老模型构建与全流程应用研究