MYSQL

SQL语句

DDL:操作数据库的
DML:操作表的CRUD
DCL:操作用户及权限

存储引擎

MyISAM:
1.查询速度快
2.不支持事务
3.只支持表锁
InnoDB
1.支持事务
2.整体速度快
3.支持表锁和行锁

什么是表锁和行锁?
https://blog.csdn.net/nicajonh/article/details/78814987
什么是事务?
ACID
原子性:要么成功,要么失败,没有中间操作
一致性:事务开始和结束,数据库的完整性没有被破坏
隔离性:事务之间互相隔离
持久性:事务操作的结果是不会丢失的

索引原理

索引数据结构:B树和B+树,减少IO操作,目录查找
索引命中:
索引类型:
分库分表
SQL注入
SQL慢查询优化:

MYSQL主从:binglog
MYSQL读写分离
MYSQL主主(MGR)

Go操作Mysql

准备数据库

  1. #建库
  2. create database goday02 character set utf8mb4 collate utf8mb4_bin;
  3. #建用户
  4. create user 'test'@'%' identified by 'test';
  5. #赋权
  6. grant all on goday02.* to test@'%';
  7. #刷新权限
  8. FLUSH PRIVILEGES;
  9. #选择数据库
  10. use goday02;
  11. #建表
  12. CREATE TABLE `user` (
  13. `id` int NOT NULL AUTO_INCREMENT,
  14. `user_name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
  15. `age` int COLLATE utf8mb4_bin DEFAULT NULL,
  16. `city` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
  17. PRIMARY KEY (`id`)
  18. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

下载数据库驱动

go get -u github.com/go-sql-driver/mysql

使用数据库驱动

  1. package main
  2. import (
  3. "database/sql"
  4. "fmt"
  5. _ "github.com/go-sql-driver/mysql" //只执行init
  6. "time"
  7. )
  8. var db *sql.DB
  9. //安装驱动
  10. //go get -u github.com/go-sql-driver/mysql
  11. //使用database/sql库进行数据库操作
  12. //database/sql原生支持连接池功能是并发安全的,但没有具体实现只是列出了第三方库需要实现的内容
  13. func initDB() (err error) {
  14. //数据库信息
  15. dsn := "test:test@tcp(192.168.72.10:3306)/goday02"
  16. db, err = sql.Open("mysql", dsn) //不会校验数据库的账户密码信息,只校验格式
  17. if err != nil {
  18. fmt.Println("dsn error", err)
  19. return
  20. }
  21. //校验账户密码是否正确
  22. err = db.Ping()
  23. if err != nil {
  24. fmt.Println("check mysql user error", err)
  25. return
  26. }
  27. //设置数据库最大连接池数
  28. db.SetMaxOpenConns(10)
  29. //设置数据库中最大的闲置连接数
  30. db.SetMaxIdleConns(5)
  31. //设置数据库链接存活的时间
  32. db.SetConnMaxLifetime(time.Second * 30)
  33. return
  34. }
  35. type User struct {
  36. Id int
  37. Name string
  38. Age int
  39. City string
  40. }
  41. //QueryRowDemo 单行查询
  42. func QueryRowDemo() {
  43. sqlStr := `select id,user_name,age,city from user where id = ?`
  44. var u User
  45. err := db.QueryRow(sqlStr, 1).Scan(&u.Id, &u.Name, &u.Age, &u.City)
  46. if err != nil {
  47. return
  48. }
  49. fmt.Println(u)
  50. }
  51. //QueryDemo 多行查询
  52. func QueryDemo() {
  53. sqlStr := `select id,user_name,age,city from user`
  54. rows, err := db.Query(sqlStr)
  55. defer rows.Close()
  56. if err != nil {
  57. return
  58. }
  59. for rows.Next() {
  60. var u User
  61. rows.Scan(&u.Id, &u.Name, &u.Age, &u.City)
  62. fmt.Println(u)
  63. }
  64. }
  65. //InsertDemo 插入数据
  66. func InsertDemo(name string, age int, city string) {
  67. sqlStr := `insert into user(user_name,age,city) values(?,?,?)`
  68. ret, err := db.Exec(sqlStr, name, age, city)
  69. if err != nil {
  70. return
  71. }
  72. //如果是插入数据操作,可以获取插入数据的id
  73. theId, err := ret.LastInsertId()
  74. if err != nil {
  75. return
  76. }
  77. fmt.Println(theId)
  78. }
  79. //UpdateDemo 更新数据
  80. func UpdateDemo(age int, id int) {
  81. sqlStr := `update user set age=? where id=?`
  82. ret, err := db.Exec(sqlStr, age, id)
  83. if err != nil {
  84. return
  85. }
  86. //如果是插入数据操作,可以获取修改数据影响的行数
  87. rowNum, err := ret.RowsAffected()
  88. if err != nil {
  89. return
  90. }
  91. fmt.Println(rowNum)
  92. }
  93. //DeleteDemo 删除数据
  94. func DeleteDemo(id int) {
  95. sqlStr := "delete from user where id=?"
  96. ret, err := db.Exec(sqlStr, id)
  97. if err != nil {
  98. return
  99. }
  100. //如果是插入数据操作,可以获取删除数据影响的行数
  101. rowNum, err := ret.RowsAffected()
  102. if err != nil {
  103. return
  104. }
  105. fmt.Println(rowNum)
  106. }
  107. func main() {
  108. initDB()
  109. defer db.Close()
  110. QueryDemo()
  111. //InsertDemo("测试",20,"北京")
  112. //UpdateDemo(24, 3)
  113. //DeleteDemo(2)
  114. //fmt.Printf("select * from user where id = %s", "ssss")
  115. }

Mysql预处理

为什么要预处理?
1.优化mysql服务器重复执行SQL的方法,可以提升服务器效率,提前让服务器编译,批量执行重复操作,一次编译多次执行
2.避免SQL注入的问题

Go预处理操作

  1. // QueryPrepareDemo 查询预处理
  2. func QueryPrepareDemo() {
  3. sqlStr := `select id,user_name,age,city from user where id > ?`
  4. stmt, err := db.Prepare(sqlStr)
  5. defer stmt.Close()
  6. if err != nil {
  7. return
  8. }
  9. rows, err := stmt.Query(0)
  10. defer rows.Close()
  11. if err != nil {
  12. return
  13. }
  14. for rows.Next() {
  15. var u User
  16. rows.Scan(&u.Id, &u.Name, &u.Age, &u.City)
  17. fmt.Println(u)
  18. }
  19. }
  20. // InsertPrepareDemo 新增预处理
  21. func InsertPrepareDemo(name string, age int, city string) {
  22. sqlStr := `insert into user(user_name,age,city) values(?,?,?)`
  23. stmt, err := db.Prepare(sqlStr)
  24. defer stmt.Close()
  25. if err != nil {
  26. return
  27. }
  28. ret, err := stmt.Exec(name, age, city)
  29. if err != nil {
  30. return
  31. }
  32. //如果是插入数据操作,可以获取插入数据的id
  33. theId, err := ret.LastInsertId()
  34. if err != nil {
  35. return
  36. }
  37. fmt.Println(theId)
  38. }

Mysql事务

Go事务操作

GO中事务主要为三个函数
tx,err:=db.Begin()
tx.Rollback()
tx.Commit()

  1. //开启事务
  2. func transactionUpdateDemo(age,id int) {
  3. //开启事务
  4. tx, err := db.Begin()
  5. if err!=nil{
  6. return
  7. }
  8. sqlStr := `update user set age=? where id=?`
  9. ret, err := tx.Exec(sqlStr, age, id)
  10. if err != nil {
  11. //回滚
  12. tx.Rollback()
  13. return
  14. }
  15. //如果是插入数据操作,可以获取修改数据影响的行数
  16. rowNum, err := ret.RowsAffected()
  17. if err != nil {
  18. //回滚
  19. tx.Rollback()
  20. return
  21. }
  22. //提交
  23. err = tx.Commit()
  24. if err != nil {
  25. //回滚
  26. tx.Rollback()
  27. return
  28. }
  29. fmt.Println(rowNum)
  30. }

SQLX第三方包操作msyql

sqlx查询与原有操作不同,其他操作大致相同

  1. package main
  2. import (
  3. "fmt"
  4. _ "github.com/go-sql-driver/mysql" //只执行init
  5. "github.com/jmoiron/sqlx"
  6. "time"
  7. )
  8. //安装sqlx go get -u github.com/jmoiron/sqlx
  9. var dbx *sqlx.DB
  10. func initXDB() (err error) {
  11. //数据库信息
  12. dsn := "test:test@tcp(192.168.72.10:3306)/goday02"
  13. dbx, err = sqlx.Open("mysql", dsn) //不会校验数据库的账户密码信息,只校验格式
  14. if err != nil {
  15. fmt.Println("dsn error", err)
  16. return
  17. }
  18. //校验账户密码是否正确
  19. err = dbx.Ping()
  20. if err != nil {
  21. fmt.Println("check mysql user error", err)
  22. return
  23. }
  24. //设置数据库最大连接池数
  25. dbx.SetMaxOpenConns(10)
  26. //设置数据库中最大的闲置连接数
  27. dbx.SetMaxIdleConns(5)
  28. //设置数据库链接存活的时间
  29. dbx.SetConnMaxLifetime(time.Second * 30)
  30. return
  31. }
  32. type User struct {
  33. Id int `db:"id"`
  34. Name string `db:"user_name"`
  35. Age int `db:"age"`
  36. City string `db:"city"`
  37. }
  38. //QueryRowXDemo 单行查询
  39. func QueryRowXDemo() {
  40. sqlStr := `select id,user_name,age,city from user where id = ?`
  41. var u User
  42. err := dbx.Get(&u, sqlStr, 1)
  43. if err != nil {
  44. return
  45. }
  46. fmt.Println(u)
  47. }
  48. //QueryXDemo 多行查询
  49. func QueryXDemo() {
  50. sqlStr := `select id,user_name,age,city from user`
  51. var u []User
  52. err := dbx.Select(&u, sqlStr)
  53. if err != nil {
  54. return
  55. }
  56. fmt.Println(u)
  57. }
  58. func main() {
  59. initXDB()
  60. QueryXDemo()
  61. }