GO语言(三十二):访问关系型数据库(下)在本节中go语言实现的数据库,您将使用 Go 执行 SQL INSERT语句以向数据库添加新行 。
您已经了解了如何使用Query和QueryRow处理返回数据go语言实现的数据库的 SQL 语句 。要执行不返回数据的 SQL 语句,请使用Exec.
1、在albumByID下面,粘贴以下addAlbum函数以在数据库中插入新专辑,然后保存 main.go 。
在此代码中:
(1)用DB.Exec执行INSERT语句 。
Exec接受一条 SQL 语句,后跟 SQL 语句的参数值 。
(2)检查尝试INSERT中的错误 。
(3)使用Result.LastInsertId检索插入的数据库行的 ID。
(4)检查尝试检索 ID 的错误 。
2、更新main以调用新addAlbum函数 。
在main函数末尾添加以下代码 。
在新代码中:
(1)调用addAlbum添加新专辑,将要添加的专辑的 ID 分配给albID变量 。
从包含 main.go 目录的命令行中,运行代码 。
恭喜!您刚刚使用 Go 对关系数据库执行了简单的操作 。
本节包含您使用本教程构建的应用程序的代码 。
使用Go实现一个数据库连接池开始本文之前 , 我们看一段Go连接数据库的代码:
本文内容我们将解释连接池背后是如何工作的 , 并 探索 如何配置数据库能改变或优化其性能 。
转自:
整理:地鼠文档:
那么sql.DB连接池是如何工作的呢?
需要理解的最重要一点是,sql.DB池包含两种类型的连接——“正在使用”连接和“空闲”连接 。当您使用连接执行数据库任务(例如执行SQL语句或查询行)时,该连接被标记为正在使用,任务完成后,该连接被标记为空闲 。
当您使用Go执行数据库操作时 , 它将首先检查池中是否有可用的空闲连接 。如果有可用的连接 , 那么Go将重用这个现有连接,并在任务期间将其标记为正在使用 。如果在您需要空闲连接时池中没有空闲连接,那么Go将创建一个新的连接 。
当Go重用池中的空闲连接时,与该连接有关的任何问题都会被优雅地处理 。异常连接将在放弃之前自动重试两次,这时Go将从池中删除异常连接并创建一个新的连接来执行该任务 。
连接池有四个方法,我们可以使用它们来配置连接池的行为 。让我们一个一个地来讨论 。
SetMaxOpenConns()方法允许您设置池中“打开”连接(使用中 空闲连接)数量的上限 。默认情况下,打开的连接数是无限的 。
一般来说,MaxOpenConns设置得越大 , 可以并发执行的数据库查询就越多,连接池本身成为应用程序中的瓶颈的风险就越低 。
但让它无限并不是最好的选择 。默认情况下,PostgreSQL最多100个打开连接的硬限制,如果达到这个限制的话,它将导致pq驱动返回”sorry, too many clients already”错误 。
为了避免这个错误,将池中打开的连接数量限制在100以下是有意义的 , 可以为其他需要使用PostgreSQL的应用程序或会话留下足够的空间 。
设置MaxOpenConns限制的另一个好处是,它充当一个非常基本的限流器,防止数据库同时被大量任务压垮 。
但设定上限有一个重要的警告 。如果达到MaxOpenConns限制,并且所有连接都在使用中,那么任何新的数据库任务将被迫等待,直到有连接空闲 。在我们的API上下文中,用户的HTTP请求可能在等待空闲连接时无限期地“挂起” 。因此,为了缓解这种情况,使用上下文为数据库任务设置超时是很重要的 。我们将在书的后面解释如何处理 。
【go语言实现的数据库 go语言数据库操作】SetMaxIdleConns()方法的作用是:设置池中空闲连接数的上限 。缺省情况下,最大空闲连接数为2 。
理论上,在池中允许更多的空闲连接将增加性能 。因为它减少了从头建立新连接发生概率—,因此有助于节省资源 。
但要意识到保持空闲连接是有代价的 。它占用了本来可以用于应用程序和数据库的内存 , 而且如果一个连接空闲时间过长,它也可能变得不可用 。例如,默认情况下MySQL会自动关闭任何8小时未使用的连接 。
因此,与使用更小的空闲连接池相比,将MaxIdleConns设置得过高可能会导致更多的连接变得不可用,浪费资源 。因此保持适量的空闲连接是必要的 。理想情况下,你只希望保持一个连接空闲 , 可以快速使用 。
另一件要指出的事情是MaxIdleConns值应该总是小于或等于MaxOpenConns 。Go会强制保证这点,并在必要时自动减少MaxIdleConns值 。
SetConnMaxLifetime()方法用于设置ConnMaxLifetime的极限值,表示一个连接保持可用的最长时间 。默认连接的存活时间没有限制,永久可用 。
如果设置ConnMaxLifetime的值为1小时,意味着所有的连接在创建后,经过一个小时就会被标记为失效连接,标志后就不可复用 。但需要注意:
理论上,ConnMaxLifetime为无限大(或设置为很长生命周期)将提升性能,因为这样可以减少新建连接 。但是在某些情况下 , 设置短期存活时间有用 。比如:
如果您决定对连接池设置ConnMaxLifetime,那么一定要记住连接过期(然后重新创建)的频率 。例如 , 如果连接池中有100个打开的连接,而ConnMaxLifetime为1分钟,那么您的应用程序平均每秒可以杀死并重新创建多达1.67个连接 。您不希望频率太大而最终影响性能吧 。
SetConnMaxIdleTime()方法在Go 1.15版本引入对ConnMaxIdleTime进行配置 。其效果和ConnMaxLifeTime类似,但这里设置的是:在被标记为失效之前一个连接最长空闲时间 。例如,如果我们将ConnMaxIdleTime设置为1小时 , 那么自上次使用以后在池中空闲了1小时的任何连接都将被标记为过期并被后台清理操作删除 。
这个配置非常有用,因为它意味着我们可以对池中空闲连接的数量设置相对较高的限制,但可以通过删除不再真正使用的空闲连接来周期性地释放资源 。
所以有很多信息要吸收 。这在实践中意味着什么?我们把以上所有的内容总结成一些可行的要点 。
1、根据经验,您应该显式地设置MaxOpenConns值 。这个值应该低于数据库和操作系统对连接数量的硬性限制,您还可以考虑将其保持在相当低的水平,以充当基本的限流作用 。
对于本书中的项目,我们将MaxOpenConns限制为25个连接 。我发现这对于小型到中型的web应用程序和API来说是一个合理的初始值,但理想情况下 , 您应该根据基准测试和压测结果调整这个值 。
2、通常,更大的MaxOpenConns和MaxIdleConns值会带来更好的性能 。但是,效果是逐渐降低的,而且您应该注意 , 太多的空闲连接(连接没有被复用)实际上会导致性能下降和不必要的资源消耗 。
因为MaxIdleConns应该总是小于或等于MaxOpenConns,所以对于这个项目,我们还将MaxIdleConns限制为25个连接 。
3、为了降低上面第2点的风险,通常应该设置ConnMaxIdleTime值来删除长时间未使用的空闲连接 。在这个项目中,我们将设置ConnMaxIdleTime持续时间为15分钟 。
4、ConnMaxLifetime默认设置为无限大是可以的,除非您的数据库对连接生命周期施加了硬限制,或者您需要它协助一些操作,比如优雅地交换数据库 。这些都不适用于本项目,所以我们将保留这个默认的无限制配置 。
与其硬编码这些配置,不如更新cmd/api/main.go文件通过命令行参数读取配置 。
ConnMaxIdleTime值比较有意思 , 因为我们希望它传递一段时间,最终需要将其转换为Go的time.Duration类型 。这里有几个选择:
1、我们可以使用一个整数来表示秒(或分钟)的数量,并将其转换为time.Duration 。
2、我们可以使用一个表示持续时间的字符串——比如“5s”(5秒)或“10m”(10分钟)——然后使用time.ParseDuration()函数解析它 。
3、两种方法都可以很好地工作,但是在这个项目中我们将使用选项2 。继续并更新cmd/api/main.go文件如下:
File: cmd/api/main.go
go语言postgresql数据库驱动怎么用PostgreSQL和MySQL比较,它更加庞大一点,因为它是用来替代Oracle而设计的 。所以在企业应用中采用PostgreSQL是一个明智的选择 。
现在MySQL被Oracle收购之后,有传闻Oracle正在逐步的封闭MySQL,,鉴于此 , 将来我们也许会选择PostgreSQL而不是MySQL作为项目的后端数据库 。
1、驱动
Go实现的支持PostgreSQL的驱动也很多,因为国外很多人在开发中使用了这个数据库 。
支持database/sql驱动,纯Go写的
支持database/sql驱动,纯Go写的
支持database/sql驱动,纯Go写的
在下面的示例中我采用了第一个驱动,因为它目前使用的人最多,在github上也比较活跃 。
2、实例代码
数据库建表语句:
复制代码
CREATE TABLE userinfo
(
uid serial NOT NULL,
username character varying(100) NOT NULL,
departname character varying(500) NOT NULL,
Created date,
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE);
CREATE TABLE userdeatail
(
uid integer,
intro character varying(100),
profile character varying(100)
)
WITH(OIDS=FALSE);
复制代码
看下面这个Go如何操作数据库表数据:增删改查
复制代码
package main
import (
"database/sql"
"fmt"
_ "github.com/bmizerany/pq"
)
func main() {
db, err := sql.Open("postgres", "user=astaxie password=astaxie dbname=test sslmode=disable")
checkErr(err)
//插入数据
stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3) RETURNING uid")
checkErr(err)
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
checkErr(err)
//pg不支持这个函数,因为他没有类似MySQL的自增ID
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
//更新数据
stmt, err = db.Prepare("update userinfo set username=$1 where uid=$2")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", 1)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
//查询数据
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created string
err = rows.Scan(uid, username, department, created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
//删除数据
stmt, err = db.Prepare("delete from userinfo where uid=$1")
checkErr(err)
res, err = stmt.Exec(1)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
复制代码
从上面的代码我们可以看到,PostgreSQL是通过$1,$2这种方式来指定要传递的参数,而不是MySQL中的? , 另外在sql.Open中的dsn信息的格式也与MySQL的驱动中的dsn格式不一样,所以在使用时请注意它们的差异 。
还有pg不支持LastInsertId函数 , 因为PostgreSQL内部没有实现类似MySQL的自增ID返回,其他的代码几乎是一模一样
GO语言(三十):访问关系型数据库(上)本教程介绍go语言实现的数据库了使用 Godatabase/sql及其标准库中的包访问关系数据库的基础知识 。
您将使用的database/sql包包括用于连接数据库、执行事务、取消正在进行的操作等的类型和函数 。
在本教程中go语言实现的数据库 , 您将创建一个数据库go语言实现的数据库,然后编写代码来访问该数据库 。您的示例项目将是有关老式爵士乐唱片的数据存储库 。
首先,为您要编写的代码创建一个文件夹 。
1、打开命令提示符并切换到您的主目录 。
在 Linux 或 Mac 上go语言实现的数据库:
在 Windows 上:
2、在命令提示符下 , 为您的代码创建一个名为 data-access 的目录 。
3、创建一个模块,您可以在其中管理将在本教程中添加的依赖项 。
运行go mod init命令,为其提供新代码的模块路径 。
此命令创建一个 go.mod 文件,您添加的依赖项将在其中列出以供跟踪 。
注意:在实际开发中,您会指定一个更符合您自己需求的模块路径 。有关更多信息,请参阅一下文章 。
GO语言(二十五):管理依赖项(上)
GO语言(二十六):管理依赖项(中)
GO语言(二十七):管理依赖项(下)
接下来,您将创建一个数据库 。
在此步骤中,您将创建要使用的数据库 。您将使用 DBMS 本身的 CLI 创建数据库和表 , 以及添加数据 。
您将创建一个数据库,其中包含有关黑胶唱片上的老式爵士乐录音的数据 。
这里的代码使用MySQL CLI,但大多数 DBMS 都有自己的 CLI , 具有类似的功能 。
1、打开一个新的命令提示符 。
在命令行 , 登录到您的 DBMS,如下面的 MySQL 示例所示 。
2、在mysql命令提示符下,创建一个数据库 。
3、切到您刚刚创建的数据库,以便您可以添加表 。
4、在文本编辑器的 data-access 文件夹中,创建一个名为 create-tables.sql 的文件来保存用于添加表的 SQL 脚本 。
将以下 SQL 代码粘贴到文件中,然后保存文件 。
在此 SQL 代码中:
(1)删除名为album表 。首先执行此命令可以让您更轻松地稍后重新运行脚本 。
(2)创建一个album包含四列的表:title、artist和price 。每行的id值由 DBMS 自动创建 。
(3)添加带有值的四行 。
5、在mysql命令提示符下,运行您刚刚创建的脚本 。
您将使用以下形式的source命令:
6、在 DBMS 命令提示符处,使用SELECT语句来验证您是否已成功创建包含数据的表 。
接下来,您将编写一些 Go 代码进行连接,以便进行查询 。
现在你已经有了一个包含一些数据的数据库,开始你的 Go 代码 。
找到并导入一个数据库驱动程序 , 该驱动程序会将您通过database/sql包中的函数发出的请求转换为数据库可以理解的请求 。
1、在您的浏览器中,访问SQLDrivers wiki 页面以识别您可以使用的驱动程序 。
2、使用页面上的列表来识别您将使用的驱动程序 。为了在本教程中访问 MySQL , 您将使用 Go-MySQL-Driver 。
3、请注意驱动程序的包名称 - 此处为github.com/go-sql-driver/mysql.
4、使用您的文本编辑器 , 创建一个用于编写 Go 代码的文件,并将该文件作为 main.go 保存在您之前创建的数据访问目录中 。
5、进入main.go,粘贴以下代码导入驱动包 。
在此代码中:
(1)将您的代码添加到main包中,以便您可以独立执行它 。
(2)导入 MySQL 驱动程序github.com/go-sql-driver/mysql 。
导入驱动程序后 , 您将开始编写代码以访问数据库 。
现在编写一些 Go 代码,让您使用数据库句柄访问数据库 。
您将使用指向结构的指针sql.DB , 它表示对特定数据库的访问 。
编写代码
1、进入 main.go,在import您刚刚添加的代码下方,粘贴以下 Go 代码以创建数据库句柄 。
在此代码中:
(3)使用 MySQL 驱动程序Config和FormatDSN类型以收集连接属性并将它们格式化为连接字符串的 DSN 。
该Config结构使代码比连接字符串更容易阅读 。
(4)调用sql.Open 初始化db变量 , 传递 FormatDSN 。
(5)检查来自 的错误sql.Open 。例如,如果您的数据库连接细节格式不正确,它可能会失败 。
为了简化代码,您调用log.Fatal结束执行并将错误打印到控制台 。在生产代码中,您会希望以更优雅的方式处理错误 。
(6)调用DB.Ping以确认连接到数据库有效 。在运行时 , sql.Open可能不会立即连接,具体取决于驱动程序 。您在Ping此处使用以确认 database/sql包可以在需要时连接 。
(7)检查来自Ping的错误,以防连接失败 。
(8)Ping如果连接成功,则打印一条消息 。
文件的顶部现在应该如下所示:
3、保存 main.go 。
1、开始跟踪 MySQL 驱动程序模块作为依赖项 。
使用go get 添加 github.com/go-sql-driver/mysql 模块作为您自己模块的依赖项 。使用点参数表示“获取当前目录中代码的依赖项” 。
2、在命令提示符下,设置Go 程序使用的DBUSER和DBPASS环境变量 。
在 Linux 或 Mac 上:
在 Windows 上:
3、在包含 main.go 的目录中的命令行中,通过键入go run来运行代码 。
连接成功了go语言实现的数据库!
接下来,您将查询一些数据 。
Golang database/sql源码分析Gorm是Go语言开发用的比较多的一个ORM 。它的功能比较全:
但是这篇文章中并不会直接看Gorm的源码,我们会先从database/sql分析 。原因是Gorm也是基于这个包来封装的一些功能 。所以只有先了解了database/sql包才能更加好的理解Gorm源码 。
database/sql 其实也是一个对于mysql驱动的上层封装 。”github.com/go-sql-driver/mysql”就是一个对于mysql的驱动,database/sql 就是在这个基础上做的基本封装包含连接池的使用
下面这个是最基本的增删改查操作
操作分下面几个步骤:
因为Gorm的连接池就是使用database/sql包中的连接池,所以这里我们需要学习一下包里的连接池的源码实现 。其实所有连接池最重要的就是连接池对象、获取函数、释放函数下面来看一下database/sql中的连接池 。
DB对象
获取方法
释放连接方法
连接池的实现有很多方法,在database/sql包中使用的是chan阻塞 使用map记录等待列表,等到有连接释放的时候再把连接传入等待列表中的chan 不在阻塞返回连接 。
之前我们看到的Redigo是使用一个chan 来阻塞,然后释放的时候放入空闲列表 , 在往这一个chan中传入struct{}{},让程序继续 获取的时候再从空闲列表中获取 。并且使用的是链表的结构来存储空闲列表 。
database/sql 是对于mysql驱动的封装,然而Gorm则是对于database/sql的再次封装 。让我们可以更加简单的实现对于mysql数据库的操作 。
go数据库有哪些官网go数据库有sql2go官网 。
用于将 sql 语句转换为 golang 的 struct. 使用 ddl 语句即可 。例如对于创建表的语句: show create table xxx. 将输出的语句,直接粘贴进去就行 。toml2go网 。用于将编码后的 toml 文本转换问 golang 的 struct 。
非关系型数据库(NoSQL):
指的是分布式的、非关系型的、不保证遵循ACID原则的数据存储系统 。NoSQL数据库技术与CAP理论、一致性哈希算法有密切关系 。所谓CAP理论,简单来说就是一个分布式系统不可能满足可用性、一致性与分区容错性这三个要求 。
一次性满足两种要求是该系统的上限 。而一致性哈希算法则指的是NoSQL数据库在应用过程中 , 为满足工作需求而在通常情况下产生的一种数据算法 , 该算法能有效解决工作方面的诸多问题但也存在弊端,即工作完成质量会随着节点的变化而产生波动 。
go语言实现的数据库的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于go语言数据库操作、go语言实现的数据库的信息别忘了在本站进行查找喔 。
推荐阅读
- 零基础体育足球游戏教案,零基础体育足球游戏教案中班
- 信号下载,信号下载 ftp
- 双人玩的飞行游戏,双人玩的飞行游戏推荐
- cpu1080是什么意思,cpu10870是坑吗
- 自定义linux命令 linux 自定义命令行
- python怎么实现鼠标绘制图形,python 操作鼠标
- flutter复杂界面,flutter 界面
- 外国小孩玩射击游戏的电影,外国小孩玩游戏视频
- c语言中的函数怎么表示 c 语言 函数