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