传送门: 柏链项目学院

什么是Bolt?

  Bolt是一个纯净的基于go语言编写的key-val数据库,该项目受到LMDB项目的启发,目标是提供一个不需要完整服务器的简单、快速、可靠的数据库。

  Bolt稳定,API固定,文件格式固定。全单元测试覆盖和随机黑盒测试用于确保数据库一致性和线程安全性。Bolt目前用于高负载生产环境,为1TB的数据库提供服务。Shopify和Heroku等许多公司每天都使用Bolt支持的服务。

  唯一不好的一点作者自认为没时间更新了,以下为作者原文:

Bolt的最初目标是提供一个简单的纯Go键/值存储,并且不会使具有无关功能的代码膨胀。为此,该项目取得了成功。但是,这个有限的范围也意味着项目已经完成。

维护开源数据库需要大量的时间和精力。对代码的更改可能会产生意想不到的,有时甚至是灾难性的影响,因此即使是简单的更改也需要数小时和数小时的仔细测试和验证。

不幸的是,我不再有时间或精力继续这项工作。Bolt处于稳定状态,并且已经成功使用了多年。因此,我认为将其置于当前状态是最谨慎的行动方式。

如果您有兴趣使用更具特色的Bolt版本,我建议您查看名为bbolt的CoreOS分支

Bolt使用介绍

安装手册使用参考

安装

go get github.com/boltdb/bolt

使用以及相关API

  本文不详细介绍具体API用法,而是结合使用,将相关的API进行具体介绍。

Bolt的组织结构是:db(数据库) -- bucket(桶)-- key/val(键值对)

  • Open 打开数据库

  Open函数可以获得一个db对象,db对象对应一个Close函数

db, err := bolt.Open("my.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
  • Update 读写操作模式

    dbptr 为之前Open函数返回的数据库操作指针,或者可以理解为我们之前使用数据库进行操作的连接。

  CreateBucketIfNotExists 是创建一个bucket的函数,也可以直接使用CreateBucket,名字长的这个相对安全一点,如果存在就不创建了,否则将会报错!

Put函数就是设置key-val对的函数,设置的内容存放在对应的bucket当中。

func setData(key, val string) error {
//以读写方式操作数据库
dbptr.Update(func(tx *bolt.Tx) error {
//创建水桶
b, err := tx.CreateBucketIfNotExists([]byte(bucket))
if err != nil {
fmt.Println("failed to create bucket", err)
return err
}
//设置key-val对
return b.Put([]byte(key), []byte(val))
})
return nil
}
  • View 只读操作模式

此种模式不涉及到对数据的修改,只有读取数据部分,同样是需要找到相同的bucket,然后寻找对应的key值。

View就是以只读方式操作数据库。

Get函数可以获得bucket中的key值。

func getData(key string) string {
data := []byte{}
//以只读方式操作数据库
dbptr.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(bucket))
data = b.Get([]byte(key))
return nil
})
return string(data)
}
  • 事务的支持

  万万没想到的是,这么小的数据库还能支持事务。事务的特点就是一次执行的多个数据库操作,要么一起成功,要么一起失败!这个是关系型数据库的必备特点,当发生错误时一个rollback就可以恢复现场,避免出现垃圾数据。关于ACID的问题,我们本文不进行讨论。我们重点来说说如何使用API以实现事务。

Begin函数代表开启一个事务。

Rollback函数可以在出错时回滚事务。

Commit函数在事务执行没有问题之后,进行整体提交。

func transactionTest() {
//开启一个事务
tx, err := dbptr.Begin(true)
if err != nil {
fmt.Println("failed to ")
}
//函数退出时回滚
defer tx.Rollback()
//找到一个水桶
b := tx.Bucket([]byte(bucket))
//设置name对应的值是fuhongxue
err = b.Put([]byte("name"), []byte("fuhongxue")) return //在这里return是有很大区别的,此时不会执行后面的commit,而是执行rollback
if err != nil {
fmt.Println("failed to put name", err)
return
}
//执行到这里时提交事务
tx.Commit()
}

完整测试代码如下:

package main

import (
"fmt" "github.com/boltdb/bolt"
) var dbptr *bolt.DB const bucket = "mybucket" func setData(key, val string) error {
//以读写方式操作数据库
dbptr.Update(func(tx *bolt.Tx) error {
//创建水桶
b, err := tx.CreateBucketIfNotExists([]byte(bucket))
if err != nil {
fmt.Println("failed to create bucket", err)
return err
}
//设置key-val对
return b.Put([]byte(key), []byte(val))
})
return nil
} func getData(key string) string {
data := []byte{}
//以只读方式操作数据库
dbptr.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(bucket))
data = b.Get([]byte(key))
return nil
})
return string(data)
} func transactionTest() {
//开启一个事务
tx, err := dbptr.Begin(true)
if err != nil {
fmt.Println("failed to ")
}
//函数退出时回滚
defer tx.Rollback()
//找到一个水桶
b := tx.Bucket([]byte(bucket))
//设置name对应的值是fuhongxue
err = b.Put([]byte("name"), []byte("fuhongxue")) return //在这里return是有很大区别的,此时不会执行后面的commit,而是执行rollback
if err != nil {
fmt.Println("failed to put name", err)
return
}
//设置name对应的值是fuhongxue2
err = b.Put([]byte("name"), []byte("fuhongxue2"))
if err != nil {
fmt.Println("failed to put name", err)
return
}
//执行到这里时提交事务
tx.Commit()
} func main() {
//打开数据库文件,这个文件用于存放数据库的数据
db, err := bolt.Open("db.db", 0600, nil)
if err != nil {
fmt.Println("failed to open db file", err)
return
}
dbptr = db
defer dbptr.Close()
setData("name", "yekai")
transactionTest()
fmt.Println(getData("name"))
}

大家猜一猜执行结果会如何呢?

yekaideMacBook-Pro:test yk$ go run db.go
yekai

  因为transactionTest中存在一个return,导致事务并没有被提交,所以val值就是yekai,仍然与setData后的结果相同。

把return注释之后再来尝试以下!

yekaideMacBook-Pro:test yk$ go run db.go
fuhongxue2

  代码编写到此位置,通过使用可以发现,Bolt使用确实非常便捷!为了更好的理解,我们总结一下Bolt的使用和结构,都在图里了!

这么小的key-val数据库居然也支持事务——与短跑名将同名的数据库Bolt的更多相关文章

  1. 根据数据库帮助类采用事务插入图片到sql server数据库中

    我们定义数据库为image类型,然后读取图片为字符流,再保存到数据库中,首先我们定义一个读取图片的公共类,此公共类以后会用到,所以可以建立相应的帮助类 public static byte[] Rea ...

  2. 一个支持DbFirst、ModelFirst和CodeFirst的数据库小工具DbTool

    DbTool 一个支持DbFirst.ModelFirst和CodeFirst的数据库工具. 简介 这是一个针对 SqlServer 数据库和 C# 开发语言的小工具,可以利用这个小工具生成数据库表对 ...

  3. 小D课堂 - 零基础入门SpringBoot2.X到实战_第8节 数据库操作之整合Mybaties和事务讲解_32..SpringBoot2.x持久化数据方式介绍

    笔记 1.SpringBoot2.x持久化数据方式介绍          简介:介绍近几年常用的访问数据库的方式和优缺点 1.原始java访问数据库             开发流程麻烦        ...

  4. php笔记08:数据库编程---使用php的MySQL扩展库操作MySQL数据库

    1.使用php的MySQL扩展库操作MySQL数据库: php有3种方式操作MySQL数据库 (1)mysql扩展库 (2)mysqli扩展库 (3)pdo     mysql扩展库与mysql数据库 ...

  5. MySQL数据库_索引_事务_优化 _锁_存储引擎_存储过程_CAP

    ##一.基础 ## *    插入                   INSERT INTO table_name ( field1, field2,...fieldN )              ...

  6. MySQL数据库之索引、事务、存储引擎详细讲解

    一.索引 1.1 索引的概念 索引是一个排序的列表,存储着索引值和这个值所对应的物理地址 无须对整个表进行扫描,通过物理地址就可以找到所需数据 (数据库索引类似书中的目录,通过目录就可以快速査找所需信 ...

  7. Redis系列之key操作命令与Redis中的事务详解(六)

    序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...

  8. DBHelper (支持事务与数据库变更) z

    using System; using System.Data; using System.Data.Common; using Project.BaseFramework; using System ...

  9. 共享参数ContentProvider 类与数据库绑定,如何通过共享参数测试类,测试数据库的增删改查功能

    Intent可以传一个对象 当两个界面之间跳转时,需要传递一个对象过去,是通过使用Bundle类,并且实体类需要serializable实现序列化,传递方法如下: 定义一个静态常量作为key值 pub ...

随机推荐

  1. [Swift]LeetCode1014. 最佳观光组合 | Best Sightseeing Pair

    Given an array A of positive integers, A[i] represents the value of the i-th sightseeing spot, and t ...

  2. JDK 8u131

    JDK 8u131 发布了.Java SE 8u131 包括重要的安全修复和bug修复.Oracle 强烈建议所有 JavaSE 8 用户升级到此版本.此次完整版本号为1.8.0_131-b11. J ...

  3. 运行PHP后台项目:xampp下载,安装,配置,运行PHP的web项目

    本来没有想着弄PHP,但是有同学叫我帮忙启动一下一个PHP写的后台.着实需要去学习一下. 想着安装xampp软件,一个集合了多个服务器,多个数据库,多个后台语言的管理软件. 一.xampp下载 二.安 ...

  4. JVM基础系列第4讲:从源代码到机器码,发生了什么?

    在上篇文章我们聊到,无论什么语言写的代码,其到最后都是通过机器码运行的,无一例外.那么对于 Java 语言来说,其从源代码到机器码,这中间到底发生了什么呢?这就是今天我们要聊的. 如下图所示,编译器可 ...

  5. JVM基础系列开篇:为什么要学虚拟机?

    跟许多人一样,我一开始接触 Java 虚拟机只是因为面试需要用到,所以硬着头皮看看.所以很多人对于为什么要学虚拟机这个问题,他们的答案都是:因为面试.但我经过了几年的学习和实战,我发现其实学习虚拟机并 ...

  6. 【干货】基于Owin WebApi 使用OAuth2进行客户端授权服务

    前言:采用Client Credentials方式,即密钥key/password,场景一般是分为客户端限制必须有权限才能使用的模块,这和微信公众号开放平台很类似. 让用户通过客户端去获取自己的tok ...

  7. Java基础5:抽象类和接口

    本文主要介绍了抽象类和接口的特性和使用方法. 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl.g ...

  8. PC逆向之代码还原技术,第六讲汇编中除法代码还原以及原理第二讲,被除数是正数 除数非2的幂

    目录 一丶简介 二丶代码还原讲解 1.被除数无符号 除数非2的幂 2.被除数无符号 除数为特例7 三丶代码还原总结 一丶简介 上一篇博客说的除2的幂. 如果被除数是有符号的,那么会进行调整,并使用位操 ...

  9. 深度学习框架Keras介绍及实战

    Keras 是一个用 Python 编写的高级神经网络 API,它能够以 TensorFlow, CNTK, 或者 Theano 作为后端运行.Keras 的开发重点是支持快速的实验.能够以最小的时延 ...

  10. BUG心得

    在<程序员,你会从 Bug 中学习么?>一文中,我写了我是怎样追踪这些年遇到的最有趣 bug 的.最近我重新浏览了这所有的 194 个条目(历时 13 年),看看我从这些 bug 中学到了 ...