RDS for MySQL
MySQL是目前最受欢迎的开源数据库之一,其性能卓越,成为WEB开发的高效解决方案。 云数据库 RDS for MySQL拥有稳定可靠、安全运行、弹性伸缩、轻松管理、经济实用等特点。
- 架构成熟稳定,支持流行应用程序,适用于多领域多行业;支持各种WEB应用,成本低,中小企业首选。
- 管理控制台提供全面的监控信息,简单易用,灵活管理,可视又可控。
- 随时根据业务情况弹性伸缩所需资源,按需开支,量身订做。
环境准备
本节内容将为您演示如何使用以 Go 语言编写的代码连接到 RDS for MySQL。 同时还介绍了在数据库中查询、插入、更新和删除数据。
项目地址:MySQL samples
代码连接
-
购买RDS for MySQL实例后,可通过三种连接方式连接实例,你可根据需要选择。Go代码连接方式如下:
//连接mysql func InitDB() (err error) { // DSN:Data Source Name dsn, err := getDSN() if err != nil { return } Db, err = sql.Open("mysql", dsn) if err != nil { return errors.Wrap(err, "ERR: fail to open mysql") } // 尝试与数据库建立连接(校验数据源是否正确) err = Db.Ping() if err != nil { return errors.Wrap(err, "ERR: fail to connect db") } Db.SetMaxOpenConns(10) Db.SetMaxIdleConns(2) return } -
云数据库参数保存在yaml文件中,关键代码如下:
//获取配置参数 func getDSN() (dsn string, err error) { config, err := GetConfig() if err != nil { return } root := config.Name password := config.Password host := config.Host port := config.Port database := config.Database dsn = fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", root, password, host, port, database) return }字段说明,如下:
host:数据库IP或者域名(推荐使用内网)
port:数据库实例映射端口,默认3306
database:数据库名
root:数据库用户名
password:数据库密码
基础操作
-
插入数据
func insertRowDemo(db *sql.DB) error { sqlStr := "insert into animals(name, age) values (?,?)" _, err := db.Exec(sqlStr, "老虎", 3) if err != nil { return errors.Wrap(err, "ERR: fail to insertRow") } return nil } -
更新数据
//更新数据 func updateRowDemo(db *sql.DB) error { sqlStr := "update animals set age=? where id = ?" ret, err := db.Exec(sqlStr, 39, 1) if err != nil { return errors.Wrap(err, "ERR: fail to updateRow") } n, err := ret.RowsAffected() // 操作影响的行数 if err != nil { return errors.Wrap(err, "ERR: fail to get rows") } fmt.Printf("update success, affected rows:%d\n", n) return nil } -
删除数据
// 删除数据 func deleteRowDemo(db *sql.DB) error { sqlStr := "delete from animals where id = ?" ret, err := db.Exec(sqlStr, 3) if err != nil { return errors.Wrap(err, "ERR: fail to deleteRow") } n, err := ret.RowsAffected() // 操作影响的行数 if err != nil { return errors.Wrap(err, "ERR: fail to get rows") } fmt.Printf("delete success, affected rows:%d\n", n) return nil } -
查询数据
// 查询多条数据示例 func queryMultiRowDemo(db *sql.DB) error { sqlStr := "select id, name, age from animals where id > ?" rows, err := db.Query(sqlStr, 0) if err != nil { return errors.Wrap(err, "ERR: fail to queryRow") } // 非常重要:关闭rows释放持有的数据库链接 defer rows.Close() // 循环读取结果集中的数据 for rows.Next() { var u animals err := rows.Scan(&u.id, &u.name, &u.age) if err != nil { return errors.Wrap(err, "ERR: fail to scan row") } fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age) } return nil }
常见问题
对于一般的sql语句的执行过程,一般流程是这样的:
- 客户端对SQL语句中的占位符进行替换得到最终SQL语句。
- 然后送把这个SQL语句发送到MySQL服务端
- MySQL服务端执行SQL语句把结果返回给客户端
而对于预处理进行的执行过程,流程是这样的:
- 先将SQL语句分成命令部分与数据部分。
- 然后先把命令部分发送给MySQL服务端,MySQL服务端进行SQL预处理。
- 最后把数据部分发送给MySQL服务端,MySQL服务端对SQL语句的占位符进行替换。
- MySQL服务端执行完整的SQL语句并将结果返回给客户端。
预处理优点:能优化重复执行的sql,提升服务器性能。避免SQL注入。
GO实现预处理示例代码
// 预处理查询示例
func prepareDemo() {
sqlStr := "select id, name, age from user where id > ?"
//预处理方法
stmt, err := db.Prepare(sqlStr)
if err != nil {
return errors.Wrap(err, "ERR: fail to prepare")
return
}
defer stmt.Close()
rows, err := stmt.Query(0)
if err != nil {
return errors.Wrap(err, "ERR: fail to query")
}
defer rows.Close()
// 循环读取结果集中的数据
for rows.Next() {
var anim animals
err := rows.Scan(&anim.id, &anim.name, &anim.age)
if err != nil {
return errors.Wrap(err, "ERR: fail to scan")
}
fmt.Printf("id:%d name:%s age:%d\n", anim.id, anim.name, anim.age)
}
}
GO连接MySQL数据库还可使用ORM框架,通常采用GORM框架,使用文档参考GORM官方文档,具体项目参考Go入门Web项目