前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >modernc.org/sqlite驱动SQLite并发读写研究

modernc.org/sqlite驱动SQLite并发读写研究

原创
作者头像
一介程序员
发布2023-07-17 10:53:18
6110
发布2023-07-17 10:53:18
举报

背景

针对Go语言modernc.org/sqlite驱动并发读写过程中的报错“database is locked (5) (SQLITE_BUSY)”的研究。

测试代码

代码语言:go
复制
package main

import (
	"database/sql"
	"fmt"
	"sync"
	"time"

	_ "modernc.org/sqlite"
)

func main() {

	var db, err = sql.Open("sqlite", "db.sqlite")
	if err != nil {
		panic("connect db error" + err.Error())
	}
	defer db.Close()

	db.Exec("PRAGMA journal_mode = wal;")
	db.Exec("PRAGMA busy_timeout = 10000;")
	db.Exec("DROP TABLE IF EXISTS user;")
	db.Exec("CREATE TABLE user(id integer primary key, name text not null, age integer not null);")
	db.Exec("insert into user(name, age) values('user1', 1);")

	if res, err := db.Query("PRAGMA journal_mode;"); err != nil {
		panic("query error:" + err.Error())
	} else {
		for res.Next() {
			var mode string
			if err := res.Scan(&mode); err != nil {
				panic("scan error:" + err.Error())
			}
			fmt.Printf("journal_mode:%s\n", mode)
		}
		res.Close()
	}

	wg := sync.WaitGroup{}
	wr := sync.RWMutex{}

	startT := time.Now()

	for wi := 0; wi < 10; wi++ {
		wg.Add(1)
		go func(idx int) {
			for i := 0; i < 10000; i++ {

				wr.Lock()
				if _, err := db.Exec("update user set age = ? where id = 1;", i); err != nil {
					panic("update error:" + err.Error())
				}
				wr.Unlock()

			}
			wg.Done()
			fmt.Printf("update %d done\n", idx)
		}(wi)
	}

	for ri := 0; ri < 10; ri++ {
		wg.Add(1)
		go func(idx int) {
			for i := 0; i < 10000; i++ {

				wr.Lock()
				if res, err := db.Query("select * from user where id = 1;"); err != nil {
					panic("query error:" + err.Error())
				} else {
					res.Close()
				}
				wr.Unlock()

			}
			wg.Done()
			fmt.Printf("query %d done\n", idx)
		}(ri)
	}

	wg.Wait()

	tc := time.Since(startT)

	fmt.Printf("time cost:%s\n", tc.String())

}

结论

  1. journal_mode = walbusy_timeout = 10000 无法保证并发读写不报错;
  2. 读写锁无法保证并发读写不报错(包括并发读);
  3. 所有SQL操作都用写锁,能保证并发读写不报错。

另外,wal模式性能提升明显,测试记录如下(测试环境:win10;i7-10700k;WD_BLACK SN750 1T):

代码语言:txt
复制
journal_mode:delete
update 0 done
query 2 done 
update 6 done
update 9 done
update 1 done
query 0 done 
query 6 done 
update 8 done
query 5 done 
update 2 done
query 3 done 
update 5 done
query 1 done
query 7 done
query 9 done
query 8 done
update 3 done
update 4 done
update 7 done
query 4 done
time cost:1m17.0827793s

journal_mode:wal
query 8 done
update 0 done
query 2 done
update 4 done
query 6 done
update 1 done
query 0 done
query 9 done
update 2 done
update 5 done
query 4 done
query 1 done
update 9 done
update 7 done
update 8 done
query 3 done
update 3 done
query 7 done
query 5 done
update 6 done
time cost:31.9394113s

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 测试代码
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档