Go資料庫查詢底層流程

2021-09-26 10:40:12 字數 3279 閱讀 8424

一般寫法:

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有很大的影響,而且對應用程式的擴充套件有非常大的影響.所以對應用程式來說,乙個具有良好設計的資料庫是非常重要的.那麼如何才能設計出效能好,又支援擴充套件的資料庫呢?這是我們大家都要去探索的問題.現在有很多版本的資料庫設計的流程.然而這也只是...