日期:2014-05-16 浏览次数:20646 次
?
H2数据库的版本: 1.3.169
?
server端有一个listen线程,
org.h2.server.TcpServer.listen()
?
此线程一直在监听客户端连接,
一但收到客户端连接请求就开一个新的线程处理它(并未使用线程池、每连接每线程)
?
?
协议共有18条命令(从0到17)
?
?
?
client先发数据:
int minClientVersion int maxClientVersion String db //数据库名 String URL String userName byte[] userPasswordHash //32字节,使用SHA256算法对 userName + "@" + userPassword 进行hash,作为用户保存到数据库中的密码 byte[] filePasswordHash //32字节,使用SHA256算法对 "file@" + filePassword 进行hash,用来加密数据库文件 int keys length //url中的key-value参数个数 keys length个 { String key String value }?
?
当前支持的协议版本是6、7、8、9、10、11、12
?
minClientVersion和maxClientVersion用来告诉server端当前client能支持的最小和最大协议版本是多少,
根据这两个参数,server端会选择一个合适的协议版本与client通信,
选择合适的协议版本的方法如下:
6<=minClientVersion<=12,
如果maxClientVersion>=12,那么就用12,否则使用minClientVersion
?
?
server响应: STATUS_OK 或 STATUS_ERROR
?
STATUS_OK: ------------------------------------ int STATUS_OK(1) int clientVersion ------------------------------------ STATUS_ERROR: ------------------------------------ int STATUS_ERROR(0) String SQLState value String message String sql int errorCode String trace ------------------------------------ 见org.h2.server.TcpServerThread.sendError(Throwable)?
?
?
?
client自己生成一个长度为64个字符的sessionId,然后传给server,
client给server发送的是一个SESSION_SET_ID数据包
?
sessionId在server端会在内存中保存,当client调用org.h2.jdbc.JdbcStatement.cancel()时才用到
?
------------------------------------
int ? ? SESSION_SET_ID(12)
String ?sessionId
------------------------------------
?
server响应: 只有STATUS_OK
------------------------------------
int ? ? STATUS_OK(1)
------------------------------------
?
?
上面的1和2在client和server之间每次建立一个新的connection(或称为session)时都会固定发送,
(见: org.h2.engine.SessionRemote.initTransfer(ConnectionInfo, String, String))
?
?
?
?
?
?
接下来按执行SQL语句的类别分成两类: QUERY和UPDATE
?
执行SQL之前,需要先进行prepare,
client给server发送的是一个SESSION_PREPARE_READ_PARAMS或SESSION_PREPARE数据包,两者格式几本上一样,
SESSION_PREPARE_READ_PARAMS需要server响应的数据包中包含SQL语句中的参数元数据,SESSION_PREPARE则不需要,
SESSION_PREPARE用在第二次对同一个SQL进行prepare时。
?
SESSION_PREPARE_READ_PARAMS
------------------------------------
int ? ? SESSION_PREPARE_READ_PARAMS(11)
int ? ? id(执行当前sql时为此操作生成的一个计数器)
String ?sql
------------------------------------
?
server响应:
------------------------------------
int ? ? STATUS_OK 或 STATUS_OK_STATE_CHANGED
boolean isQuery
boolean readonly
int ? ? sql parameter size
Parameter MetaData[]
------------------------------------
?
SESSION_PREPARE
------------------------------------
int ? ? SESSION_PREPARE(0)
int ? ? id(执行当前sql时为此操作生成的一个计数器)
String ?sql
------------------------------------
?
server收到上面两个包后,会按id把对应的SQL缓存起来,
server响应:
------------------------------------
int ? ? STATUS_OK 或 STATUS_OK_STATE_CHANGED
boolean isQuery
boolean readonly
int ? ? sql parameter size
------------------------------------
?
相关源代码见: org.h2.command.CommandRemote.prepare(SessionRemote, boolean)
?
?
?
?
当进行java.sql.Statement.executeUpdate之类的操作时通常会触发update
?
COMMAND_EXECUTE_UPDATE
------------------------------------
int ? ? COMMAND_EXECUTE_UPDATE(3)
int ? ? id(对应prepare阶段生