1. 程式人生 > 其它 >go-操作mysql資料庫go-操作mysql資料庫

go-操作mysql資料庫go-操作mysql資料庫

1.mysql原始命令

a.登入

登入:
mysql -u root -p密碼  //連本機的

SELECT User, Host, Password FROM mysql.user;  //檢視使用者

新增新使用者:
create user 'liuxuan14'@'localhost' identified by '123456';
修改密碼:
set password for 'liuxuan14'@'localhost'=password('1998');
為使用者授權:
//允許訪問所有資料庫下的所有表
grant all privileges on *.* to '新使用者名稱'@'指定ip' identified by '新使用者密碼' ;
//指定資料庫下的指定表
grant all privileges on test.test to '新使用者名稱'@'指定ip' identified by '新使用者密碼' ;
//只擁有查詢許可權
grant select on *.* to '新使用者名稱'@'指定ip' identified by '新使用者密碼' WITH GRANT OPTION;
FLUSH PRIVILEGES;  //重新整理許可權

刪除使用者:
drop user liuxuan@localhost;

連線遠端資料庫:
MySQL 連線遠端資料庫(192.168.5.116),埠“3306”,使用者名稱為“root”,密碼“123456”
mysql -h 192.168.5.116 -P 3306 -u root -p123456
mysql -h ip -P 埠 -A -u name  -p 密碼

create database name

b.建表

CREATE TABLE IF NOT EXISTS `mytable`(
   `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '自增',
   `app_id` bigint NOT NULL DEFAULT '0' COMMENT '應用id',
   `time` int NOT NULL DEFAULT '0' COMMENT '時間',
   `date` DATE,
   PRIMARY KEY ( `id` )
   UNIQUE KEY `idx_app` (`app_id`) USING BTREE
   KEY `idx_ip` (`machine_ip`) USING BTREE,
   KEY `idx_app_machineid` (`app_id`,`machine_id`) USING BTREE
)ENGINE=InnoDB DEFAULT COMMENT='表名';

AUTO_INCREMENT定義列為自增的屬性,一般用於主鍵,數值會自動加1。
PRIMARY KEY關鍵字用於定義列為主鍵。 您可以使用多列來定義主鍵,列間以逗號分隔。
ENGINE 設定儲存引擎,CHARSET 設定編碼。

表結構:desc name;
建表語句:show create tablename;

註釋

註釋:comment
create table test1 ( 
    field_name int comment '欄位的註釋' 
)comment='表的註釋';
修改表的註釋:
alter table test1 comment '修改後的表的註釋';
修改欄位的註釋:
alter table test1 modify column field_name int comment '修改後的欄位註釋'; 
查看錶註釋:
show  create  table  test1; 
檢視欄位註釋:
show  full  columns  from  test1; 

索引

唯一索引:
UNIQUE KEY
1  主鍵是一種約束,唯一索引是一種索引,兩者在本質上是不同的。
2  主鍵建立後一定包含一個唯一性索引,唯一性索引不一定就是主鍵。
3   唯一性索引列允許空值, 而主鍵列不允許為空值。
4   主鍵可以被其他表引用為外來鍵,而唯一索引不能。
5   一個表最多隻能建立一個主鍵,但是可以建立多個唯一索引。
6   主鍵更適合那些不容易改變的唯一標識,如自動遞增列,身份證號等。
7   在RBO 模式下,主鍵的執行計劃優先順序高於唯一索引。兩者可以提高查詢的速度。

c.新增一個欄位

alter table tablename add `app_name` varchar(16) NOT NULL DEFAULT '';

d.修改資料

update tablename set 欄位='修改的值' where 條件;
多個欄位中間加,

e.刪除

刪庫:drop database name;
刪表:drop table name;

mysql刪除一行:
delete from 表 where 條件;

f.新增一行

insert into tablename (app_id,machine_id,machine_ip,ctime,use_perc) values(?,?,?,?,?);   //對應欄位加

insert into 表名 values(int,'string')(..);  //可一次性加多行,一行全部數都有

insert into 表名 set 列名='', ...;

2.go操作資料庫

使用:database/sql包

mysql預設埠號3306

檢視:mysql內,show global variables like 'port';

檢視mysql配置檔案目錄:

mysql --help|grep 'my.cnf'

a.建立連線池

//1.建立連線池
func newPool() *sql.DB {  //sql.DB 表示一個連線池
	cfg := mysql.NewConfig()
	cfg.User = "name"
	cfg.Passwd = "123456"
	cfg.Net = "tcp"
	cfg.Addr = "127.0.0.1:3306"
	cfg.DBName = "mydb"
	dsn := cfg.FormatDSN()

	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Fatal(err)
	}
	if err := db.Ping(); err != nil { //ping測試網路連通性及使用者密碼是否正確
		log.Fatal(err)
	}
	return db
}

b.query查詢

func QueryUser(id int64) (*User, error) {
  var db = newPool()  //建立連線
	rows, err := db.Query("select `id`, `name` from `users` where `id` = ?", id)
	if err != nil {
		return nil, err
	}
	defer rows.Close() // 注意這裡,一定要關閉
	user := User{}
	for rows.Next() {
		if err := rows.Scan(&user.ID, &user.Name); err != nil {
			return nil, err
		}
		break
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return &user, nil
}

連線池對程式設計師是透明的,這裡並不需要顯式的從連線池裡獲取連線,而是通過連線池來執行查詢語句。
Query 方法返回一個 *Rows 指標,代表結果集。

要注意的是 defer rows.Close() 如果忘了關閉,可能會造成連線洩露。

rows.Scan 方法有個方便的特性,如果id在資料庫裡是 varchar(50) 型別,我們傳的引數&user.ID指向int64,這依然可以工作,Scan 方法會執行自動轉換。

c.單行查詢queryrow

// QueryUser1 單行查詢
func QueryUser1(id int64) (*User, error) {
	row := pool.QueryRow("select `id`, `name` from `users` where `id` = ?", id)
	user := User{}
	if err := row.Scan(&user.ID, &user.Name); err != nil {
		if err == sql.ErrNoRows {
			return nil, nil  // 返回 (*User)(nil) 表示查詢結果不錯在
		}
		return nil, err
	}
	return &user, nil
}

d.插入更新刪除exec

// InsertUser 插入使用者
func InsertUser(name string) (int64, error) {
	res, err := pool.Exec("insert into `users` (`name`) values (?)", name)
	if err != nil {
		return 0, err
	}
	return res.LastInsertId()
}
// UpdateUser 更新使用者
func UpdateUser(id int64, name string) error {
	_, err := pool.Exec("update `users` set `name` = ? where `id` = ?", name, id)
	if err != nil {
		return err
	}
	return nil
}
// DeleteUser 刪除使用者
func DeleteUser(id int64) error {
	_, err := pool.Exec("delete from `users` where `id` = ?", id)
	if err != nil {
		return err
	}
	return nil
}

e.事務

// UpdateFooBar 更新
func UpdateFooBar(id int64, x, y string) (err error) {
	tx, err := pool.Begin()
	if err != nil {
		return
	}
	defer func() {
		switch {
		case err != nil:
			tx.Rollback()
		default:
			err = tx.Commit()
		}
	}()

	_, err = tx.Exec("update `foo` set `x` = ? where `id` = ?", x, id)
	if err != nil {
		return
	}
	_, err = tx.Exec("update `bar` set `y` = ? where `id` = ?", y, id)
	if err != nil {
		return
	}

	return
}

3.mysql加鎖

讀鎖全表鎖(LOCK TABLE 表 READ)
讀鎖行鎖(SELECT ... LOCK IN SHARE MODE)
寫鎖全表鎖(LOCK TABLE 表 WRITE)
寫鎖行鎖(SELECT ... FOR UPDATE)

鎖總體可以分為樂觀鎖和悲觀鎖,簡單說,樂觀鎖用版本號控制,悲觀鎖用鎖控制。
樂觀鎖:核心原理是增加一個version的欄位來控制。新增一個version欄位,每個更新時where條件都加上它,並且也更新它UPDATE users SET name="雪山飛豬",version=version+1 WHERE id=3 AND version=0 UPDATE users SET name="chenqionghe",version=version+1 WHERE id=3 AND version=0。這就是最簡單的CAS機制。
悲觀鎖:類似Go語言裡的Mutex和RwMutex

共享鎖(S鎖)又稱讀鎖,若事務T對資料物件A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S 鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。

排他鎖(X鎖)又稱寫鎖。若事務T對資料物件A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。

寫鎖表鎖:
加鎖:lock table kiss_share_idproducer write;
此時其他程序無法讀也無法寫。
解鎖:unlock table;
--------------------------------
寫鎖行鎖:
begin;
加鎖:select * from  kiss_share_idproducer where app_id=21 for update;
其他再加鎖,等待,直到佔鎖的commit;
更新:update kiss_share_idproducer set mix_id=7 where app_id=21;
解鎖:commit;
讀鎖表鎖:
加鎖:lock table kiss_share_idproducer read;
此時其他程序可以讀但無法寫。
解鎖:unlock table;
-------------------------------
讀鎖行鎖:
加鎖:select * from  kiss_share_idproducer where app_id=21 lock in share mode;
其他再加鎖,等待,直到佔鎖的commit;
更新:update kiss_share_idproducer set mix_id=7 where app_id=21;
解鎖:commit;

參考

go的mysql操作:https://blog.csdn.net/embinux/article/details/84031620

mysql加鎖:https://blog.csdn.net/weixin_33838871/article/details/113566444