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

news/2025/2/11 8:33:16/

因为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.ppmy.cn/news/1571112.html

相关文章

方舟字节码原理剖析:架构、特性与实践应用

方舟字节码原理剖析&#xff1a;架构、特性与实践应用 一、引言 在当今软件行业高速发展的大背景下&#xff0c;应用程序的性能、开发效率以及跨平台兼容性成为了开发者们关注的核心要素。编译器作为软件开发流程中的关键工具&#xff0c;其性能和特性直接影响着软件的质量和…

DeePseek结合PS!批量处理图片的方法教程

​ ​ 今天我们来聊聊如何利用deepseek和Photoshop&#xff08;PS&#xff09;实现图片的批量处理。 传统上&#xff0c;批量修改图片尺寸、分辨率等任务往往需要编写脚本或手动处理&#xff0c;而现在有了AI的辅助&#xff0c;我们可以轻松生成PS脚本&#xff0c;实现自动化处…

51单片机俄罗斯方块开机显示界面

/************************************************************************************************************** * 名称&#xff1a;Data_Cover * 功能&#xff1a;整屏写入 * 参数&#xff1a;array&#xff0c;为开机显示界面数据 * 返回&#xff1a;NULL * 备注&…

基于 Git、Jenkins 和 Docker 的自动化持续集成与部署实践

摘要&#xff1a; 在现代软件开发中&#xff0c;持续集成&#xff08;CI&#xff09;和持续部署&#xff08;CD&#xff09;已成为提升开发效率和软件质量的关键实践。通过将 Git、Jenkins 和 Docker 三者结合&#xff0c;可以构建一个高效的自动化构建、测试和部署流水线。 …

Enterprise Architect 17 全面升级:重塑建模体验,赋能复杂系统设计

在数字化转型的浪潮中&#xff0c;复杂系统设计已成为企业创新和发展的重要推动力。作为一款广受认可的建模工具&#xff0c;Sparx Systems 的 Enterprise Architect&#xff08;EA&#xff09;以其丰富的功能和灵活性&#xff0c;赢得了全球用户的信赖。近日&#xff0c;Sparx…

【Unity】性能优化:UI的合批 图集和优化

目录 前言一、合批测试二、图集 前言 注意&#xff1a;DC指的是Draw Call。 温馨小提示&#xff1a;Frame Debugger 窗口&#xff08;菜单&#xff1a;Window > Analysis > Frame Debugger&#xff09;会显示绘制调用信息&#xff0c;并允许您控制正在构建的帧的“回放”…

Redis企业开发实战(五)——点评项目之分布式锁Redission与秒杀优化

目录 一、Redisson (一)Redisson基本介绍 (二)Redisson入门 1.引入依赖 2.配置Redisson客户端 3.使用Redission的分布式锁 4.tryLock参数解析 4.1tryLock() 4.2tryLock(long waitTime, TimeUnit unit) 4.3tryLock(long waitTime, long leaseTime, TimeUnit unit) 4…

电子时钟html

要求&#xff1a; 电子时钟的时间需与北京时间实时对应。 原理&#xff1a; 获取当地时间&#xff0c;我发现不用UTC8&#xff0c;当地时间已经与北京时间一致。获取时分秒&#xff0c;小于十的补零。调用clock更新&#xff0c;这样刷新的时候还会有内容。设置每秒钟调用一次。…