本文翻译自https://github.com/go-sql-driver/mysql/
Go-MySQL-Driver 用于Go语言database/sql
包的MySQL驱动。
特性
- 轻量又快速
- 纯Go语言实现,并非是对C语言的封装
- 通过TCP/IPv4、TCP/IPv6、Unix域套接字或自定义协议进行连接
- 自动处理断开的连接
- 自动连接池(通过
database/sql
包) - 支持大于16MB的查询字符串
- 完整的
sql.RawBytes
支持 - 智能地处理预处理语句中的
LONG DATA
- 通过文件白名单安全地支持
LOAD DATA LOCAL INFILE
,也支持io.Reader
- 可选的
time.Time
解析 - 可选的占位符插值
要求
- Go 1.13或更高版本。我们的目标是支持Go的3个最新版本。
- MySQL (4.1+)、MariaDB、Percona Server、Google CloudSQL或Sphinx (2.2.3+)
安装
使用shell中的go工具将包简单地安装到你的$GOPATH
中:
$ go get -u github.com/go-sql-driver/mysql
确保Git安装在你的机器上和系统的PATH
中。
用法
Go语言MySQL驱动是Go的database/sql/driver
包的接口的实现。你只需要导入这个驱动,然后就可以使用完整的database/sql
包的API。
使用mysql
作为driverName
,使用有效的DSN作为dataSourceName
:
import (
"database/sql"
"time"
_ "github.com/go-sql-driver/mysql"
)
// ...
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
panic(err)
}
// 参见“重要设置”小节。
db.SetConnMaxLifetime(time.Minute * 3)
db.SetMaxOpenConns(10)
db.SetMaxIdleConns(10)
重要设置
db.SetConnMaxLifetime()
确保连接在MySQL服务器、操作系统或其他中间件关闭之前由驱动程序安全地关闭。由于某些中间件会在5分钟后关闭空闲连接,因此我们建议把超时时间设置为短于5分钟的时间。此设置也有助于负载平衡和更改系统变量。
db.SetMaxOpenConns()
强烈建议使用该函数来限制应用程序使用的连接数。没有建议的限制数,因为它取决于具体应用程序和MySQL服务器。
db.SetMaxIdleConns()
建议设置为与db.SetMaxOpenConns()
的相同。当它小于SetMaxOpenConns()
的设置时,连接打开和关闭的频率可能比你预期的要高得多。空闲连接可以通过db.SetConnMaxLifetime()
设置超时时间。如果你想更快地关闭空闲连接,从Go 1.15开始,你可以使用db.SetConnMaxIdleTime()
函数来设置。
DSN(Data Source Name,数据源名称)
数据源名称具有一个通用格式,例如PEAR DB所使用的,但没有类型前缀(用方括号标记可选部分):
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
完整形式的DSN:
username:password@protocol(address)/dbname?param=value
除了数据库名称之外,所有值都是可选的。因此,最小DSN为:
/dbname
如果不想预先选择一个数据库实例,请将dbname
保留为空:
/
这与空DSN字符串的效果相同。
或者,我们也可以使用Config.FormatDSN通过填充一个结构体来创建DSN字符串。
密码
密码可以由任何字符组成,无需转义。
协议
有关可用网络的更多信息,请参阅net.Dial。一般来说,如果可以,你应该使用Unix域套接字,否则应该使用TCP,以获得最佳性能。
地址
对于TCP和UDP网络,地址的格式为host[:port]
。如果省略port
,将使用默认端口号。如果主机使用IPv6地址,则必须将其括在方括号中。函数net.JoinHostPort和net.SplitHostPort以这种形式处理地址。
对于Unix域套接字,地址是MySQL服务的套接字的绝对路径,例如:
/var/run/mysqld/mysqld.sock
或
/tmp/mysql.sock
参数
参数区分大小写!
请注意,true
、TRUE
、True
或1
中的任何一个表示布尔值“真”。毫不奇怪,布尔值“假”可以指定为以下任意值:false
、FALSE
、False
或0
。
allowAllFiles
Type: bool
Valid Values: true, false
Default: false
allowAllFiles=true
禁用LOAD DATA LOCAL INFILE
的文件白名单,并允许所有文件。可能不安全!
allowCleartextPasswords
Type: bool
Valid Values: true, false
Default: false
allowCleartextPasswords=true
在帐户需要时允许使用明文(cleartext)客户端插件,例如使用PAM身份验证插件定义的插件。以明文形式发送密码在某些配置中可能是一个安全问题。如果密码有可能被拦截,为避免出现问题,客户端应使用保护密码的方法连接到MySQL服务器,包括使用TLS/SSL、IPsec或专用网络。
allowFallbackToPlaintext
Type: bool
Valid Values: true, false
Default: false
allowFallbackToPlaintext=true
的作用类似于使用--ssl-mode=PREFERRED
选项的MySQL客户端,如用于连接到服务器的命令选项中所述
allowNativePasswords
Type: bool
Valid Values: true, false
Default: true
allowNativePasswords=false
禁止使用MySQL本机密码(native password)方式。
allowOldPasswords
Type: bool
Valid Values: true, false
Default: false
allowOldPasswords=true
允许使用不安全的旧密码(old password)方式。应该避免使用这种方式,但在某些情况下是必要的。另请参阅old_passwords维基页面。
charset
Type: string
Valid Values: <name>
Default: none
设置用于客户端-服务器交互的字符集(“SET NAMES <value>
“)。如果设置了多个字符集(用逗号分隔),则在设置当前字符集失败时继续尝试设置后续的字符集。例如, (charset=utf8mb4,utf8
)设置utf8mb4
(在MySQL 5.5.3中引入),如果是旧服务器就回退到utf8
。
不鼓励使用charset
参数,因为它会向服务器发出额外的查询。除非你需要回退行为,否则请改用collation
参数。
checkConnLiveness
Type: bool
Valid Values: true, false
Default: true
在支持的平台上,Go从连接池中检索连接,在使用该连接之前会检查其是否活动。如果不活动,则将相应的连接标记为坏连接,并尝试使用另一个连接。checkConnLiveness=false
不检查连接是否活动。
collation
Type: string
Valid Values: <name>
Default: utf8mb4_general_ci
设置连接时用于客户端-服务器交互的字符排序规则。与charset
不同,collation
不会发出额外的查询。如果指定的排序规则在目标服务器上不可用,则连接将失败。
可以使用SHOW COLLATION
检索服务器的有效字符集列表。
MySQL 5.5支持默认排序规则(utf8mb4_general_ci
)。对于较旧的MySQL,应该使用较旧的排序规则(例如utf8_general_ci
)。 不能使用字符集”ucs2″、”utf16″、”utf16le”和”utf32″的排序规则(参考)。
clientFoundRows
Type: bool
Valid Values: true, false
Default: false
clientFoundRows=true
会导致UPDATE语句返回匹配的行数,而不是更改的行数。
columnsWithAlias
Type: bool
Valid Values: true, false
Default: false
当columnsWithAlias=true
时,调用sql.Rows.Columns()
将返回表别名和用点分隔的列名。例如:
SELECT u.id FROM users as u
如果columnsWithAlias=true
,将返回u.id
而不仅仅是id
。
interpolateParams
Type: bool
Valid Values: true, false
Default: false
如果interpolateParams=true
,则调用db.Query()
和db.Exec()
时的占位符(?
)将插入到具有给定参数的单个查询字符串中。这减少了往返次数,因为当interpolateParams=false
时,驱动程序必须准备好一条语句,使用给定的参数执行它,然后再次关闭该语句。
这不能与多字节编码BIG5、CP932、GB2312、GBK或SJIS一起使用。这些都被拒绝,因为它们可能会引入SQL注入漏洞!
loc
Type: string
Valid Values: <escaped name>
Default: UTC
设置time.Time
值的时区(当使用parseTime=true
时)。如果时区设置为Local
,那么设置为系统的时区。有关详细信息,请参阅time.LoadLocation
。
注意,这将设置time.time
值的时区,但不会更改MySQL的time_zone设置。为此,请参见time_zone系统变量,该变量也可以设置为DSN的参数。
请记住,参数值必须是url.QueryEscape
编码的。或者,你可以手动将/
替换为%2F
。例如,US/Pacific
(美国/太平洋时区)应该被设置为loc=US%2FPacific
。
maxAllowedPacket
Type: decimal number
Default: 4194304
允许的最大数据包的大小(以字节为单位)。默认值为4MiB,应进行调整以匹配服务器设置。maxAllowedPacket=0
可用于在每次连接时从服务器自动获取max_allowed_packet
变量。
multiStatements
Type: bool
Valid Values: true, false
Default: false
是否允许在一个查询中使用多条语句。虽然这允许批量查询,但也大大增加了被SQL注入的风险。只返回第一个查询语句的结果,所有其他结果都被默默丢弃。当使用multiStatements
时,?
参数只能在第一条语句中使用。
parseTime
Type: bool
Valid Values: true, false
Default: false
parseTime=true
将DATE
和DATETIME
值的输出类型更改为time.Time
,而不是[]byte/string
类型的日期或日期时间,例如0000-00-00 00:00:00
将转换为time.Time
的零值。
readTimeout
Type: duration
Default: 0
I/O读取的超时时间。该值必须是带有单位后缀的十进制数字(”ms”、”s”、”m”、”h”),例如”30s”、”0.5m”或”1m30s”。
rejectReadOnly
Type: bool
Valid Values: true, false
Default: false
rejectReadOnly=true
会导致数据库驱动程序拒绝只读连接。这是针对自动故障切换期间可能出现的争用(race condition)情况,即故障切换后mysql客户端将连接到某个只读副本。
请注意,这应该是一种相当罕见的情况,因为自动故障转移通常发生在主服务器关闭时,并且竞态条件(race condition)不会发生,除非它在故障转移开始后立即恢复在线。另一方面,发生这种情况时,MySQL应用程序可能会卡在只读连接上,直到重新启动。然而,这种故障相当容易复现,例如在AWS Aurora的MySQL兼容集群上手动造成故障转移。
如果你不依赖只读事务来拒绝不应该发生的写入操作,那么在某些MySQL服务提供商(例如AWS Aurora)上设置此选项,对于故障切换来说更安全。
请注意,read-only
服务器可能会返回1290号错误,此选项将导致重试该错误。但是,存在其他一些情况,也使用相同的1290错误号。因此启用此选项时,应确保应用程序在read-only
模式之外,都不会导致1290号错误。
serverPubKey
Type: string
Valid Values: <name>
Default: none
可以使用mysql.RegisterServerPubKey
注册服务器的公钥,然后可以在DSN中通过参数使用该公钥。公钥用于传输加密数据,例如用于身份验证。如果服务器的公钥是已知的,则应手动设置它,以避免每次需要它时都从服务器向客户端传输,代价昂贵且可能不安全。
timeout
Type: duration
Default: OS default
建立连接时的超时时间,又称拨号超时。该值必须是带单位后缀(”ms”、”s”、”m”、”h”)的十进制数,例如”30s”、”0.5m”或”1m30s”。
tls
Type: bool / string
Valid Values: true, false, skip-verify, preferred, <name>
Default: false
tls=true
启用与服务器的TLS/SSL加密连接。如果要使用自签名或无效证书(服务器端),那么使用skip-verify
参数;或通过preferred
参数使用TLS(仅当得到服务器端建议时),这类似于skip-verify
,但还允许回退到未加密的连接。skip-verify
和preferred
都不添加任何可靠的安全性。你可以在向mysql.RegisterTLSConfig
注册后使用自定义的TLS配置。
writeTimeout
Type: duration
Default: 0
I/O写入超时。该值必须是带单位后缀(”ms”、”s”、”m”、”h”)的十进制数,例如”30s”、”0.5m”或”1m30s”。
系统变量
任何其他参数都被解释为系统变量:
<boolean_var>=<value>: SET <boolean_var>=<value>
<enum_var>=<value>: SET <enum_var>=<value>
<string_var>=%27<value>%27: SET <string_var>='<value>'
规则:
- 字符串变量的值必须用’引起来。
- 值也必须使用
url.QueryEscape
编码过(这意味着字符串变量的值必须用%27
包裹)。
例如:
autocommit=1: SET autocommit=1
time_zone=%27Europe%2FParis%27: SET time_zone='Europe/Paris'
transaction_isolation=%27REPEATABLE-READ%27: SET transaction_isolation='REPEATABLE-READ'
实例
user@unix(/path/to/socket)/dbname
root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local
user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true
通过设置系统变量sql_mode将警告视为错误:
user:password@/dbname?sql_mode=TRADITIONAL
通过IPv6的TCP:
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?timeout=90s&collation=utf8mb4_unicode_ci
远程主机上的TCP,例如Amazon RDS:
id:password@tcp(your-amazonaws-uri.com:3306)/dbname
应用引擎上的谷歌云SQL:
user:password@unix(/cloudsql/project-id:region-name:instance-name)/dbname
使用本地主机上默认端口(3306)的TCP:
user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped
使用默认协议(tcp)和主机(localhost:3306):
user:password@/dbname
未预先选择数据库:
user:password@/
连接池和超时
连接池由Go的database/sql
包管理。有关如何配置池的大小以及连接在池中停留的时间的详细信息,请参阅database/sql
文档中的*DB.SetMaxOpenConns
、*DB.Set MaxIdleConns
和*DB.Set-ConnMaxLifetime
。每个单独连接的读取、写入和拨号超时分别使用DSN参数readTimeout、writeTimeout和timeout进行配置。
支持context.Context
此驱动程序支持Go 1.8中引入的ColumnType
接口,但ColumnType.Length()
除外,该接口目前不受支持。所有无符号的数据库类型都将返回带有Unsigned
的INT
、TINYINT
、SMALLINT
或BIGINT
名称。
支持ColumnType
此驱动程序支持Go 1.8中引入的ColumnType
接口,但ColumnType.Length()
除外,该接口目前不受支持。所有无符号的数据库类型都将返回带有Unsigned
的INT
、TINYINT
、SMALLINT
或BIGINT
名称。
支持context.Context
在Go 1.8,database/sql
包添加了对context.Context
的支持。此驱动程序支持查询超时和通过context
取消语句的执行。有关详细信息,请参阅database/sql
包中的context
支持。
支持LOAD DATA LOCAL INFILE
对于此功能,你需要直接访问软件包。因此,你必须更改导入路径(无_
):
import "github.com/go-sql-driver/mysql"
文件必须通过mysql.RegisterLocalFile(filepath)
注册来明确允许加载里面的数据(推荐使用这种做法),或者必须通过使用DSN参数allowAllFiles=true
来禁用allowlist检查(这种做法可能不安全!)。
要使用io.Reader
,必须使用mysql.RegisterReaderHandler(name, handler)
注册处理函数,该函数返回io.Reador
或io.ReadCloser
。然后,Reader
可以使用文件路径Reader::<name>
。可以为不同的处理程序 handler
注册不同的名字name
,,当你不再需要它时,使用DeregisterReaderHandler
反注册。
有关详细信息,请参阅Go MySQL驱动程序的godoc。
支持time.Time
MySQL DATE
和DATETIME
值的默认内部输出类型为[]byte
,这允许你将值扫描到程序中的[]byte
、string
或sql.RawBytes
变量中。
然而,许多人希望将MySQL的DATE
和DATETIME
值扫描到Go语言的time.Time
变量中,这在逻辑上等同于MySQL中的DATE
和DATETIME
值。你可以通过使用DSN参数parseTime=true
将内部输出类型从[]byte
更改为time.Time
。你可以使用DSN参数loc
设置默认time.Time
的时区位置。
注意:截至Go 1.1,这使得time.Time
成为唯一可以扫描DATE
和DATETIME
值的变量类型。这会破坏例如对sql.RawBytes
的支持。
支持Unicode
由于1.5版本的Go MySQL驱动程序默认情况下自动使用排序规则utf8mb4_general_ci
。
可以使用DSN参数collation
设置其他排序规则/字符集。
1.0版的驱动程序建议将&charset=utf8
(即MySQL命令SET NAMES utf8
的别名)添加到DSN中,以启用正确的UTF-8支持。但现在已经没有必要这么做了,如果要设置其他排序规则/字符集的话,应该首选collation
参数。
有关MySQL的Unicode支持的更多详细信息参见http://dev.mysql.com/doc/refman/8.0/en/charset-unicode.html。
测试/开发
要运行驱动程序测试,你可能需要调整配置。有关详细信息,请参阅测试的Wiki 页面。
Go语言的MySQL驱动程序的功能还不完善。如果你想做出贡献,我们将非常感谢你的帮助,你可以处理未解决的问题或查看拉取请求。
有关详细信息,请参阅贡献指南。
License
Go语言的MySQL驱动程序在Mozilla公共许可证2.0版(Mozilla Public License Version 2.0)下获得许可。
Mozilla将许可范围总结如下:
MPL:许可证适用于任何包含MPL代码的文件。
这意味着:
- 你可以在私人和商业用途中使用未更改的源代码。
- 分发时,你必须根据a) MPL 2.0本身或b)兼容的许可证(例如GPL 3.0或Apache License 2.0)发布MPL 2.0许可的任何更改了源代码的文件。
- 只要根据MPL 2.0许可的文件未更改,你就无需发布你的库的源代码。
如果你对许可证有更多疑问,请阅读MPL 2.0的常见问题解答。
你可以在此处阅读完整条款:LICENSE。
Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
very informative articles or reviews at this time.
This is really interesting, You’re a very skilled blogger. I’ve joined your feed and look forward to seeking more of your magnificent post. Also, I’ve shared your site in my social networks!
Pretty! This has been a really wonderful post. Many thanks for providing these details.
I truly appreciate your technique of writing a blog. I added it to my bookmark site list and will
I’m often to blogging and i really appreciate your content. The article has actually peaks my interest. I’m going to bookmark your web site and maintain checking for brand spanking new information.
I like the efforts you have put in this, regards for all the great content.
very informative articles or reviews at this time.
I do not even understand how I ended up here, but I assumed this publish used to be great