本文将介绍MySQLClient和Server的通信原理,以及JavaJDBC的工作原理。什么是JDBC的Type4,什么是Type3?一、MySQLClient&Server我们在操作数据库的时候,总是通过GUI数据管理工具或者命令行连接到MySQLServer,然后进行一系列的数据库操作。创建、操作表和表中的数据等。这时候,这一系列的GUI管理工具,或者说命令行,就是一个MySQLClient,然后将Client的一系列操作命令发送给Server。这里在发送的时候,按照MySQL的规范,将Client的命令一条一条发送出去。更直观的理解,MySQL的Client和Server相当于Socket通信中的一个Client和Server,按照约定的协议格式相互通信。二、什么是JDBC?什么是JDBC?你会脱口而出,不就是通过它连接图书馆吗。这种理解只是其中的一小部分,“洒”了。JDBC全称:TheJavaDatabaseConnectivity应该从两个方面来理解。APIDriverAPI,首先是一个标准,不是针对特定的数据库,作为一种高层抽象,提供了Java语言和众多数据库之间的连接。通过JDBCAPI,我们不再需要根据不同的数据库使用不同的操作方式,而是使用一个标准的操作来实现“WriteOnce,Runanywhere”。API既然是标准,就需要有对应的实现。这里的Driver是各个数据库厂商按照标准实现的。这就是为什么在开发应用程序时,使用MySQL连接器连接MySQL,使用Oracle驱动程序连接Oracle。毕竟只有各个厂商才知道如何与自己厂商的数据库进行交互,所以根据标准,各个厂商都开发了自己的Connector。下图来自官方文档,描述了JDBC的作用以及在请求中的位置。图中左边也就是Type4,通过Driver直接连接数据库服务器。这也是最常用的,通过Driver,将JDBC请求转换成数据库服务器可以识别的协议格式。图中右侧称为Type3,将JDBC请求通过Driver转换成中间件的协议格式。以MySQL为例,我们发现JDBC的运行本质上相当于一个MySQLClient。通过Driver,将应用程序中的查询、删除等操作“翻译”成MySQLServer可以识别的协议格式。然后传递执行。因此,整个JDBC可以概括为以下三件事:创建数据库连接,发送SQL语句,处理请求结果JDBC概括了两部分,数据库服务提供者,开发XXXDriver,应用开发者使用Driver来实现连接到数据库并执行数据库操作。这样应用开发者就不需要关心底层与数据库交互时协议的实现,如何请求连接、交互等,可以更专注于自己的业务。否则,每个开发者都需要处理一次数据交互协议,繁琐困难,重复劳动。3、MySQLconnector-J的部分源码有了上面的“理论”知识,我们再来看一些东西。MySQL驱动包是开源的,我们可以很方便的下载和理解实现。JDBC最传统的使用方式一般是这样:Connectionc=DriverManager.getConnection(url,user,pwd);statementstmt=c.createStatmentstmt.executeQuery在获取结果getConnection时,一般需要提供一个URL。这个网址也是写的固定的。比如mysql就是jdbc:mysql://。这部分符合规范。同时在Driver代码中,通过解析URL获取需要连接的host、port等连接参数。publicPropertiesparseURL(Stringurl,Propertiesdefaults)throwsjava.sql.SQLException{PropertiesurlProps=(defaults!=null)?newProperties(defaults):newProperties();if(url==null){returnnull;}if(!StringUtils.startsWithIgnoreCase(url,URL_PREFIX)&&!StringUtils.startsWithIgnoreCase(url,MXJ_URL_PREFIX)&&!StringUtils.startsWithIgnoreCase(url,LOADBALANCE_URL_PREFIX)&&!StringUtils.startsWithIgnoreCase(url,REPLICATION_URL_PREFIX){returnnull;}intbeginningOfSlashes)=url.index(StringUtils.startsWithIgnoreCase(url,MXJ_URL_PREFIX)){urlProps.setProperty("socketFactory","com.mysql.management.driverlaunched.ServerLauncherSocketFactory");}查看这部分源码可以发现,除了我们常用的url配置,还可以用在其中,loadbalance配置等。我获得了知识。DriverManager.getConnection(xx,xx,xx)方法最终会调用ServiceProvider已经加载的Driver中可用的驱动,调用驱动的getConnection方法,对应Mysql的源码,也就是下面那个,以及焦点是com.mysql.jdbc。ConnectionImpl.getInstance`publicjava.sql.Connectionconnect(Stringurl,Propertiesinfo){if(url==null){throwSQLError.createSQLException(Messages.getString("NonRegisteringDriver.1"),SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE,null);}if(StringUtils.startsWithIgnoreCase(url,LOADBALANCE_URL_PREFIX)){returnconnectLoadBalanced(url,info);}elseif(StringUtils.startsWithIgnoreCase(url,REPLICATION_URL_PREFIX)){returnconnectReplicationConnection(url,info);}Propertiesprops=null;if((url,infroURL))==null){returnnull;}if(!"1".equals(props.getProperty(NUM_HOSTS_PROPERTY_KEY))){returnconnectFailover(url,info);}try{ConnectionnewConn=com.mysql.jdbc.ConnectionImpl.getInstance(host(props),端口(道具),道具,数据库(道具),网址);returnnewConn;}我们看看getInstance具体是干什么的?受保护的静态连接获取实例(StringhostToConnectTo,intportToConnectTo,Propertiesinfo,StringdatabaseToConnectTo,Stringurl)throwsSQLException{if(!Util.isJdbc4()){returnnewConnectionImpl(hostToConnectTo,portToConnectTo,信息,databaseToConnectTo,url);}返回(连接)Util.handleNewInstance(JDBC_4_CONNECTION[CTOR]{hostToConnectTo,Integer.valueOf(portToConnectTo),info,databaseToConnectTo,url},null);}this.io=newMysqlIO(newHost,newPort,mergedProps,getSocketFactoryClassName(),getProxy(),getSocketTimeout(),this.largeRowSizeThreshold.getValueAsInt());this.io.doHandshake(this.user,this.password,this.database);看一下,先通过MysqlIO建立IO连接,然后进行握手//savelastexceptiontopropagatetocallerifconnectionfailsS??ocketExceptionlastException=null;.Someversionsof//MySQL不监听IPv6地址所以尝试所有地址.for(inti=0;i
