本文翻译自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。
I just like the helpful information you provide in your articles
Awesome! Its genuinely remarkable post, I have got much clear idea regarding from this post
Good post! We will be linking to this particularly great post on our site. Keep up the great writing
very informative articles or reviews at this time.
Pretty! This has been a really wonderful post. Many thanks for providing these details.
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!
Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
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.
Pretty! This has been a really wonderful post. Many thanks for providing these details.
Awesome! Its genuinely remarkable post, I have got much clear idea regarding from this post