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

news2025/2/9 7:33:11

因为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_sqlite

import (
	"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        uint
	Name      string
	Age       uint8
	CreatedAt int64
	UpdatedAt 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 := 100
	batchCount := (len(users) + batchSize - 1) / batchSize
	for i := 0; i < batchCount; i++ {
		start := i * batchSize
		end := (i + 1) * batchSize
		if 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 []User
	err := gormDB.Find(&users).Error
	if err != nil {
		return nil, err
	}
	return users, nil
}

并发测试

var wg sync.WaitGroup

func 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 []User
			err := 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.coloradmin.cn/o/2295145.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于yolov11的阿尔兹海默症严重程度检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv11的阿尔兹海默症严重程度检测系统是一种创新的医疗辅助工具&#xff0c;旨在通过先进的计算机视觉技术提高阿尔兹海默症的早期诊断和病情监测效率。阿尔兹海默症是一种渐进性的神经退行性疾病&#xff0c;通常表现为认知障碍、记忆丧失和语言障碍等症状…

设计模式-生产者消费者模型

阻塞队列&#xff1a; 在介绍生产消费者模型之前&#xff0c;我们先认识一下阻塞队列。 阻塞队列是一种支持阻塞操作的队列&#xff0c;常用于生产者消费者模型&#xff0c;它提供了线程安全的队列操作&#xff0c;并且在队列为空或满时&#xff0c;能够阻塞等待&#xff0c;…

RabbitMQ介绍以及基本使用

文章目录 一、什么是消息队列&#xff1f; 二、消息队列的作用&#xff08;优点&#xff09; 1、解耦 2、流量削峰 3、异步 4、顺序性 三、RabbitMQ基本结构 四、RabbitMQ队列模式 1、简单队列模式 2、工作队列模式 3、发布/订阅模式 4、路由模式 5、主题模式 6、…

嵌入式硬件篇---OpenMV的硬件流和软件流

文章目录 前言一、硬件流控制&#xff08;Hardware Flow Control&#xff09;1. 基本原理RTSCTS 2. OpenMV中的实现• 硬件要求• 代码配置• 工作流程 二、软件流控制&#xff08;Software Flow Control&#xff09;1. 基本原理XONXOFF 2. OpenMV中的实现• 代码配置• 工作流…

【AIGC提示词系统】基于 DeepSeek R1 + ClaudeAI 易经占卜系统

上篇因为是VIP&#xff0c;这篇来一个免费的 提示词在最下方&#xff0c;喜欢的点个关注吧 引言 在人工智能与传统文化交融的今天&#xff0c;如何让AI系统能够传递传统易经文化的智慧&#xff0c;同时保持易经本身的神秘感和权威性&#xff0c;是一个极具挑战性的课题。本文将…

OpenAI 实战进阶教程 - 第十节 : 结合第三方工具的向量数据库Pinecone

面向读者群体 本节课程主要面向有一定编程基础和数据处理经验的计算机从业人员&#xff0c;如后端开发工程师、数据工程师以及对 AI 应用有浓厚兴趣的技术人员。即使你之前没使用过向量数据库&#xff0c;也可以通过本节的实操内容快速上手&#xff0c;为企业或个人项目构建强…

深入Linux系列之进程地址空间

深入Linux系列之进程地址空间 1.引入 那么在之前的学习中&#xff0c;我们知道我们创建一个子进程的话&#xff0c;我们可以在代码层面调用fork函数来创建我们的子进程&#xff0c;那么fork函数的返回值根据我们当前所处进程的上下文是返回不同的值&#xff0c;它在父进程中返…

AWK系统学习指南:从文本处理到数据分析的终极武器 介绍

目录 一、AWK核心设计哲学解析 1.1 记录与字段的原子模型 1.2 模式-动作范式 二、AWK编程语言深度解析 2.1 控制结构 说明&#xff1a; 2.2 关联数组 代码说明&#xff1a; 示例输入和输出&#xff1a; 注意事项&#xff1a; 2.3 内置函数库 三、高级应用技巧 3.1…

250207-MacOS修改Ollama模型下载及运行的路径

在 macOS 上&#xff0c;Ollama 默认将模型存储在 ~/.ollama/models 目录。如果您希望更改模型的存储路径&#xff0c;可以通过设置环境变量 OLLAMA_MODELS 来实现。具体步骤如下&#xff1a; 选择新的模型存储目录&#xff1a;首先&#xff0c;确定您希望存储模型的目标目录路…

半导体行业跨网文件交换系统

在当今这个数字化转型的时代&#xff0c;半导体行业作为技术密集型产业&#xff0c;正面临着前所未有的信息安全挑战。随着企业内外网隔离措施的加强&#xff0c;如何实现既安全又高效的跨网文件交换&#xff0c;成为了众多半导体企业的一大难题。 特别是在研发和生产过程中产生…

使用GD32F470的硬件SPI读写W25Q64

代码简单改下引脚定义便可以使用&#xff01; 使用的单片机具体型号&#xff1a;GD32F470ZGT6 简单介绍下W25Q64&#xff1a; /* W25Q64 性能参数 */ /* 容量&#xff1a;8MByte 64Mbit */ /* 有128个块&#xff0c;每个块有64KByte */ /* 每个块有16个扇区&#xff0c;每个…

02为什么 OD门和 OC门输出必须加上拉电阻?

为什么 OD&#xff08;开漏&#xff09;门和 OC&#xff08;开集&#xff09;门输出必须加上拉电阻&#xff1f; 1、首先一点&#xff0c;知道OD是说的MOS管&#xff0c;OC是说的三极管&#xff0c;二者的区别与联系大家应该都懂。 2、以OC门举例&#xff0c;芯片的OC门内部结…

AI方案调研与实践 (不定期补充)

目录 说明 1. AI云主机准备 1.1 Ollama配置 设置模型保存路径 配置模型驻留内存时间 查看GPU状况命令: nvidia-smi 2. Deepseek 2.1 安装与使用 3. LobeChat配置 参考 说明 调研并实例化各种AI方案&#xff0c;探索训练/使用方式的最佳实践。 1. AI云主机准备 可以去一…

人工智能大模型之模型蒸馏与知识蒸馏

一、背景介绍 随着人工智能技术的不断发展&#xff0c;大模型在各个领域的应用也越来越广泛。模型蒸馏&#xff08;Model Distillation&#xff09;和知识蒸馏&#xff08;Knowledge Distillation&#xff09;是两种非常重要的模型压缩技术&#xff0c;它们可以帮助我们将大型…

[手机Linux] onepluse6T 系统重新分区

一&#xff0c;刷入TWRP 1. 电脑下载 Fastboot 工具&#xff08;解压备用&#xff09;和对应机型 TWRP&#xff08;.img 后缀文件&#xff0c;将其放入前面解压的文件夹里&#xff09; 或者直接这里下载:TWRP 2. 将手机关机&#xff0c;长按音量上和下键 开机键 进入 fastbo…

k8s部署elasticsearch

前置环境&#xff1a;已部署k8s集群&#xff0c;ip地址为 192.168.10.1~192.168.10.5&#xff0c;总共5台机器。 1. 创建provisioner制备器&#xff08;如果已存在&#xff0c;则不需要&#xff09; 制备器的具体部署方式&#xff0c;参考我之前的文章&#xff1a;k8s部署rab…

本地部署DeepSeek

下载Docker Docker Desktop: The #1 Containerization Tool for Developers | Docker 下载安装ollama Download Ollama on macOS 下载完成后解压运行 终端输入 Ollama --version 输出对应版本号即为下载成功 如果没有弹出上述图片&#xff0c;浏览器输入http://localhos…

21.[前端开发]Day21-HTML5新增内容-CSS函数-BFC-媒体查询

王者荣耀-网页缩小的问题处理 为什么会产生这个问题&#xff1f;怎么去解决 可以给body设置最小宽度 1 HTML5新增元素 HTML5语义化元素 HTML5其他新增元素 2 Video、Audio元素 HTML5新增元素 - video video支持的视频格式 video的兼容性写法 HTML5新增元素 - audio audio…

nbmade-boot调用deepseek的api过程与显示

希望大家一起能参与我的新开源项目nbmade-boot: 宁波智能制造低代码实训平台 下面简单介绍调用最近大红的AI &#xff1a;deepseek的api过程与显示&#xff0c;包括前后端代码与效果图 一、后端代码 1、几个基础的java类 DeepSeekRequest .java package com.nbcio.demo.do…

Linux:安装 node 及 nvm node 版本管理工具(ubuntu )

目录 方法一&#xff1a;手动下载安装文件安装方法二&#xff1a;curl安装 方法一&#xff1a;手动下载安装文件安装 git clone 远程镜像 git clone https://gitee.com/mirrors/nvm安装 nvm bash install.sh刷新配置&#xff0c;使配置在终端生效 // 方法 1 source /root/.…