driver.go
connector.go
1 | // Connect implements driver.Connector interface. |
connection.go
startWatcher、watchCancel
startWatcher是开启了一个go协程,循环监听watcher管道的消息,watcher管道放的是Context类型的对象,接收到一个context对象以后,监听该对象的结束管道,收到context对象的结束消息以后,调用mc.cancel。
1 | func (mc *mysqlConn) startWatcher() { |
cancel函数是将传入的error保存在mc.canceled变量中,然后调用mc.cleanup。
而celanup函数的工作主要就是关闭连接。
1 | // finish is called when the query has canceled. |
startWatcher是监听watcher管道,而watcher管道里的消息是由watchCancel函数进行放入的
1 | func (mc *mysqlConn) watchCancel(ctx context.Context) error { |
startWatcher函数在连接服务器以后就调用了,之后需要监听context的时候就调用watchCancel,同一个连接同一时间只能监听一个context。
watchCanel一般会在mc.XxxContext函数中被调用,如mc.ExecContext
1 | func (mc *mysqlConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { |
在调用mc.Exec之前,先调用watchCancel来对ctx进行监听,看到这里的时候我产生了一个问题,调用sql.DB.XxxContext函数,当context超时时,返回的error是context timeout,那么这个错误到底是从哪里返回的呢。
沿着函数的调用,终于发现,context的error是由mc.readPacket和mc.writePacket返回的
1 | // Read packet to buffer 'data' |
在读写操作返回错误时,先检查mc.canceled中是否保存有error,如果有直接返回该error;前面说过,当ctx.Done有消息返回时,会调用mc.cancel,会将ctx.Err保存到mc.canceled,还会关闭连接的socket;因此在context被cancel或超时或者其他操作导致ctx.Done返回消息后,socket被被关闭,在socket上进行读写操作会返回error,然后将mc.canceled里保存的context的error返回。
packets.go
数据库驱动,其实也就是负责与数据库服务端通信的客户端,客户端只负责发送要执行的sql或者一些设置命令给服务端,并接受服务端的响应或者返回的数据。
mysql服务端与客户端之间的通信协议,参考一下的博文:
MySQL协议分析
MySQL网络协议分析
1 | // Read packet to buffer 'data' |