一般寫法:
db,err := sql.
open
("mysql"
,"root:123456@tcp(127.0.0.1:3306)/husky?charset=utf8");
rows,err := db.
query
("select * from test");
for rows.
next()
1.建立db
在執行open()之前,在程式啟動之後,會先執行mysql驅動中的init()方法,去註冊驅動到go基礎包的驅動管理中。而且這個init()方法是在呼叫open()方法時才會提前載入。然後呼叫mysql驅動中的open方法。
// sql.open實際上是呼叫的這個open方法
func
open
(drivername, datasourcename string)(
*db,
error
)if driverctx, ok := driveri.
(driver.drivercontext)
; ok
return
opendb
(connector)
,nil
}return
opendb
(dsnconnector),
nil}
// 主要任務就是dsn的解析
func
(d mysqldriver)
openconnector
(dsn string
)(driver.connector,
error
)return
&connector
,nil
}所以go中的sql.open()方法實際上是不建立連線的,也不去做認證校驗,如果要想真正的驗證連線,可以執行db.ping()方法。該方法也是真正的去建立連線,但只不過傳送的ping的資料報,沒有執行實際的查詢語句。在使用完連線也會呼叫putconn()方法放回連線池。
2.執行查詢
實際上呼叫的時querycontext()方法,引數需要ctx,這個是幫助後續執行完查詢或連線異常時釋放連線用的。query即使sql語句,如果sql要寫成「select * from table where name = ?」,則args要新增引數。
func
(db *db)
querycontext
(ctx context.context, query string
, args ...
inte***ce)(
*rows,
error)}
if err == driver.errbadconn
return rows, err
}
query方法實際包含兩部分,乙個是根據策略去生成或獲取連線,另乙個是執行真正的查詢。
func
(db *db)
query
(ctx context.context, query string
, args [
]inte***ce
, strategy connreusestrategy)
(*rows,
error
)return db.
querydc
(ctx,
nil, dc, dc.releaseconn, query, args)
}
querydc()是真正的執行查詢的方法,
func
(db *db)
querydc
(ctx, txctx context.context, dc *driverconn, releaseconn func
(error
), query string
, args [
]inte***ce)(
*rows,
error
)if ok
// 執行真正查詢,實際會呼叫mysql驅動中的querycontext()方法,
// querycontext()方法中會真正的將sql和引數轉換成符合mysql協議的包與mysql互動,
// 完成最後的查詢,返回driver.rows型別的查詢結果
rowsi, err =
ctxdriverquery
(ctx, queryerctx, queryer, query, nvdargs)})
if err != driver.errskip
// 下面是為了將dc的釋放依賴於rows,在rows遍歷完時執行close**或釋放連線
rows :=
&rows
rows.
initcontextclose
(ctx, txctx)
return rows,
nil}
}var si driver.stmt
var err error
withlock
(dc,
func()
)if err !=
nil ds :=
&driverstmt
// 利用driverstmt執行查詢
rowsi, err :=
rowsifromstatement
(ctx, dc.ci, ds, args...
)if err !=
nil// 下面是為了將dc的釋放依賴於rows,在rows遍歷完時執行close**或釋放連線
rows :=
&rows
rows.
initcontextclose
(ctx, txctx)
return rows,
nil}
這裡注意rows.initcontextclose()方法,是等待rows的next()方法遍歷完成才會close掉這個rows,進而**或釋放連線,所以如果沒有遍歷完rows,連線是不會被收回的,再有其他請求需要獲取連線就會新建立連線,在新鏈結用完**時,會判斷當前連線數是否大於最大空閒連線數,如果大於就會被close掉,如果有大量請求觸發會造成效能問題。 Oracle資料庫底層
oracle底層的架構對編寫出高效能的sql語句非常重要 例項系統全域性記憶體區域性區域 sga 和一系列的後台程序組成 pga sga的兩個領域 共享池和資料庫資料緩衝 sga共享池 地位 關鍵部分之一 作用 oracle快取程式資料的地方 庫快取記憶體 儲存sql語句的地方,儲存已經解析的語句的...
資料庫底層 事務
事務指滿足acid特性的一組操作,可以通過commit提交,rollback回滾 一.acid 1.atomicity原子性 事務是不可分割的最小單元,事務的所有操作要麼全部提交成功,要麼全部失敗回滾。回滾時根據日誌反向操作 2.consistency一致性 事務執行前後保持一致性狀態,所有事務對乙...
資料庫設計流程
資料庫作為資料的乙個容器,不但對程式的performance有很大的影響,而且對應用程式的擴充套件有非常大的影響.所以對應用程式來說,乙個具有良好設計的資料庫是非常重要的.那麼如何才能設計出效能好,又支援擴充套件的資料庫呢?這是我們大家都要去探索的問題.現在有很多版本的資料庫設計的流程.然而這也只是...