MySQL驱动阅读------Connection连接的建立,基于JDBC-----5.1.26

一般获取数据库连接的程序

Class.forName("com.mysql.jdbc.Driver");
final Connection connection = (Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/testDB","guoxiaoming","guoxiaoming");

-----------------------------

注册mysql驱动类下次再说,目前重点介绍Connection的建立

-----------------------------

public interface Connection  extends Wrapper {

JDK的Connection提供了一种标准,与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。

该Connection接口被数据库驱动类实现,保存有数据库连接中的IO类。

JDBC当中的DriverManager类封装了获取Connection对象的统一方法

public static Connection getConnection(String url, String user, String password) throws SQLException {
        java.util.Properties info = new java.util.Properties();

        // Gets the classloader of the code that called this method, may
	// be null.
	ClassLoader callerCL = DriverManager.getCallerClassLoader();

	if (user != null) {
	    info.put("user", user);
	}
	if (password != null) {
	    info.put("password", password);
	}

        return (getConnection(url, info, callerCL));
}

进入getConnection(url,info,callerCL)方法查看可以看到,

Connection result = di.driver.connect(url, info);

代码最终获取了Connection对象

对应的driver驱动类实现,在jdbc当中

public class NonRegisteringReplicationDriver extends NonRegisteringDriver {
	public NonRegisteringReplicationDriver() throws SQLException {
		super();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
	 */
	public Connection connect(String url, Properties info) throws SQLException {
		return connectReplicationConnection(url, info);
	}
}

看到connectReplicationConnection(url,info)方法在父类NonRegisteringDriver类当中

return new ReplicationConnection(masterProps, slavesProps);

看到该类

public ReplicationConnection(Properties masterProperties,
			Properties slaveProperties) throws SQLException {
		this.driver = new NonRegisteringDriver();
		this.slaveProperties = slaveProperties;
		this.masterProperties = masterProperties;

        this.initializeMasterConnection();
        this.initializeSlaveConnection();

		this.currentConnection = this.masterConnection;
	}

初始化了两个链接,一个是masterConnection 一个是slaveConnection

看注释

/**
 * Connection that opens two connections, one two a replication master, and
 * another to one or more slaves, and decides to use master when the connection
 * is not read-only, and use slave(s) when the connection is read-only.
 *
 * @version $Id: ReplicationConnection.java,v 1.1.2.1 2005/05/13 18:58:38
 *          mmatthews Exp $
 */

我们最终看到在ConnectionImpl类当中

protected static Connection getInstance(String hostToConnectTo,
			int portToConnectTo, Properties info, String databaseToConnectTo,
			String url) throws SQLException {
		if (!Util.isJdbc4()) {
			return new ConnectionImpl(hostToConnectTo, portToConnectTo, info,
					databaseToConnectTo, url);
		}

		return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR,
				new Object[] {
							hostToConnectTo, Integer.valueOf(portToConnectTo), info,
							databaseToConnectTo, url }, null);
	}

  实例化了该类的一个子类

public class JDBC4Connection extends ConnectionImpl

 通过构造方法

public JDBC4Connection(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException {
	super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url);
	// TODO Auto-generated constructor stub
}

在其父类中

protected ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info,
			String databaseToConnectTo, String url)
			throws SQLException {

		this.connectionCreationTimeMillis = System.currentTimeMillis();

		if (databaseToConnectTo == null) {
			databaseToConnectTo = "";
		}

重点关于方法

public void createNewIO(boolean isForReconnect)
			throws SQLException {
		synchronized (getConnectionMutex()) {
			// Synchronization Not needed for *new* connections, but defintely for
			// connections going through fail-over, since we might get the
			// new connection up and running *enough* to start sending
			// cached or still-open server-side prepared statements over
			// to the backend before we get a chance to re-prepare them...

			Properties mergedProps  = exposeAsProperties(this.props);

			if (!getHighAvailability()) {
				connectOneTryOnly(isForReconnect, mergedProps);

				return;
			} 

			connectWithRetries(isForReconnect, mergedProps);
		}
	}

最终我们看到在coreConnect方法中实现了具体的链接

private void coreConnect(Properties mergedProps) throws SQLException,
			IOException {
		int newPort = 3306;
		String newHost = "localhost";

		String protocol = mergedProps.getProperty(NonRegisteringDriver.PROTOCOL_PROPERTY_KEY);

		if (protocol != null) {
			// "new" style URL

			if ("tcp".equalsIgnoreCase(protocol)) {
				newHost = normalizeHost(mergedProps.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY));
				newPort = parsePortNumber(mergedProps.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, "3306"));
			} else if ("pipe".equalsIgnoreCase(protocol)) {
				setSocketFactoryClassName(NamedPipeSocketFactory.class.getName());

				String path = mergedProps.getProperty(NonRegisteringDriver.PATH_PROPERTY_KEY);

				if (path != null) {
					mergedProps.setProperty(NamedPipeSocketFactory.NAMED_PIPE_PROP_NAME, path);
				}
			} else {
				// normalize for all unknown protocols
				newHost = normalizeHost(mergedProps.getProperty(NonRegisteringDriver.HOST_PROPERTY_KEY));
				newPort = parsePortNumber(mergedProps.getProperty(NonRegisteringDriver.PORT_PROPERTY_KEY, "3306"));
			}
		} else {

			String[] parsedHostPortPair = NonRegisteringDriver
					.parseHostPortPair(this.hostPortPair);
			newHost = parsedHostPortPair[NonRegisteringDriver.HOST_NAME_INDEX];

			newHost = normalizeHost(newHost);

			if (parsedHostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) {
				newPort = parsePortNumber(parsedHostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]);
			}
		}

		this.port = newPort;
		this.host = newHost;

		this.io = new MysqlIO(newHost, newPort,
				mergedProps, getSocketFactoryClassName(),
				getProxy(), getSocketTimeout(),
				this.largeRowSizeThreshold.getValueAsInt());
		this.io.doHandshake(this.user, this.password,
				this.database);
	}

在new MysqlIO类当中的构造方法中实现

 public MysqlIO(String host, int port, Properties props,
        String socketFactoryClassName, MySQLConnection conn,
        int socketTimeout, int useBufferRowSizeThreshold) throws IOException, SQLException {
        this.connection = conn;

        if (this.connection.getEnablePacketDebug()) {
            this.packetDebugRingBuffer = new LinkedList<StringBuffer>();
        }
        this.traceProtocol = this.connection.getTraceProtocol();

        this.useAutoSlowLog = this.connection.getAutoSlowLog();

        this.useBufferRowSizeThreshold = useBufferRowSizeThreshold;
        this.useDirectRowUnpack = this.connection.getUseDirectRowUnpack();

        this.logSlowQueries = this.connection.getLogSlowQueries();

        this.reusablePacket = new Buffer(INITIAL_PACKET_SIZE);
        this.sendPacket = new Buffer(INITIAL_PACKET_SIZE);

        this.port = port;
        this.host = host;

        this.socketFactoryClassName = socketFactoryClassName;
        this.socketFactory = createSocketFactory();
        this.exceptionInterceptor = this.connection.getExceptionInterceptor();

        try {
        	this.mysqlConnection = this.socketFactory.connect(this.host,
        		this.port, props);

	        if (socketTimeout != 0) {
	        	try {
	        		this.mysqlConnection.setSoTimeout(socketTimeout);
	        	} catch (Exception ex) {
	        		/* Ignore if the platform does not support it */
	        	}
	        }

	        this.mysqlConnection = this.socketFactory.beforeHandshake();

	        if (this.connection.getUseReadAheadInput()) {
	        	this.mysqlInput = new ReadAheadInputStream(this.mysqlConnection.getInputStream(), 16384,
	        			this.connection.getTraceProtocol(),
	        			this.connection.getLog());
	        } else if (this.connection.useUnbufferedInput()) {
	        	this.mysqlInput = this.mysqlConnection.getInputStream();
	        } else {
	        	this.mysqlInput = new BufferedInputStream(this.mysqlConnection.getInputStream(),
	        			16384);
	        }

	        this.mysqlOutput = new BufferedOutputStream(this.mysqlConnection.getOutputStream(),
	        		16384);

	        this.isInteractiveClient = this.connection.getInteractiveClient();
	        this.profileSql = this.connection.getProfileSql();
	        this.autoGenerateTestcaseScript = this.connection.getAutoGenerateTestcaseScript();

	        this.needToGrabQueryFromPacket = (this.profileSql ||
	        		this.logSlowQueries ||
	        		this.autoGenerateTestcaseScript);

	        if (this.connection.getUseNanosForElapsedTime()
					&& Util.nanoTimeAvailable()) {
				this.useNanosForElapsedTime = true;

				this.queryTimingUnits = Messages.getString("Nanoseconds");
			} else {
				this.queryTimingUnits = Messages.getString("Milliseconds");
			}

			if (this.connection.getLogSlowQueries()) {
				calculateSlowQueryThreshold();
			}
        } catch (IOException ioEx) {
        	throw SQLError.createCommunicationsException(this.connection, 0, 0, ioEx, getExceptionInterceptor());
        }
    }
this.mysqlConnection = this.socketFactory.connect(this.host,this.port, props);这样就返回了Socket对象

在StandardSocketFactory类当中
if (this.host != null) {
				if (!(wantsLocalBind || wantsTimeout || needsConfigurationBeforeConnect)) {
					InetAddress[] possibleAddresses = InetAddress
							.getAllByName(this.host);

					Throwable caughtWhileConnecting = null;

					// Need to loop through all possible addresses, in case
					// someone has IPV6 configured (SuSE, for example...)

					for (int i = 0; i < possibleAddresses.length; i++) {
						try {
							this.rawSocket = new Socket(possibleAddresses[i],
									port);

							configureSocket(this.rawSocket, props);

							break;
						} catch (Exception ex) {
							caughtWhileConnecting = ex;
						}
					}

					if (rawSocket == null) {
						unwrapExceptionToProperClassAndThrowIt(caughtWhileConnecting);
					}
				} else {
					// must explicitly state this due to classloader issues
					// when running on older JVMs :(
					try {

						InetAddress[] possibleAddresses = InetAddress
								.getAllByName(this.host);

						Throwable caughtWhileConnecting = null;

						Object localSockAddr = null;

						Class<?> inetSocketAddressClass = null;

						Constructor<?> addrConstructor = null;

						try {
							inetSocketAddressClass = Class
									.forName("java.net.InetSocketAddress");

							addrConstructor = inetSocketAddressClass
									.getConstructor(new Class[] {
											InetAddress.class, Integer.TYPE });

							if (wantsLocalBind) {
								localSockAddr = addrConstructor
										.newInstance(new Object[] {
												InetAddress
														.getByName(localSocketHostname),
												new Integer(0 /*
																 * use ephemeral
																 * port
																 */) });

							}
						} catch (Throwable ex) {
							unwrapExceptionToProperClassAndThrowIt(ex);
						}

						// Need to loop through all possible addresses, in case
						// someone has IPV6 configured (SuSE, for example...)

						for (int i = 0; i < possibleAddresses.length; i++) {

							try {
								this.rawSocket = new Socket();

								configureSocket(this.rawSocket, props);

								Object sockAddr = addrConstructor
										.newInstance(new Object[] {
												possibleAddresses[i],
												Integer.valueOf(port) });
								// bind to the local port if not using the ephemeral port
								if (localSockAddr != null) {
									socketBindMethod.invoke(rawSocket,
											new Object[] { localSockAddr });
								}

								connectWithTimeoutMethod.invoke(rawSocket,
										new Object[] { sockAddr,
												Integer.valueOf(connectTimeout) });

								break;
							} catch (Exception ex) {
								this.rawSocket = null;

								caughtWhileConnecting = ex;
							}
						}

						if (this.rawSocket == null) {
							unwrapExceptionToProperClassAndThrowIt(caughtWhileConnecting);
						}

					} catch (Throwable t) {
						unwrapExceptionToProperClassAndThrowIt(t);
					}
				}

				return this.rawSocket;
			}

针对host可能对应多个ip的可能性,连接到其中一个ip之后就break退出

时间: 2024-10-27 10:28:23

MySQL驱动阅读------Connection连接的建立,基于JDBC-----5.1.26的相关文章

Windows环境下 PyQt5 如何安装MySql驱动 (PyQt5连接MYSQL时显示Driver not loaded解决方案)

参考文章: https://blog.csdn.net/qq_38198744/article/details/80261695 前文说过如何在Ubuntu环境下 为PyQt5  安装MySql驱动, 这里面主要说的是如何在Windows环境下安装MySql驱动. # -*- coding: utf-8 -*- ''' [简介] PyQt5中 处理database 例子 ''' import sys from PyQt5.QtCore import * from PyQt5.QtGui impo

windows10 下使用Pycharm2016 基于Anaconda3 Python3.6 安装Mysql驱动总结

本文记录:在PyCharm2016.3.3 中基于Anaconda3 Python3.6版本安装Python for Mysql驱动.尝试了安装Mysql-Connector成功,但是连接数据库时驱动有bug而失败:尝试安装MySQLdb,因Python版本兼容问题 失败.最终安装PyMysql成功.现将详细安装过程记录如下. 若不想折腾,且系统环境与我的一致,建议直接就安装PyMysql吧. 一,系统环境 windows10 64位,安装了Anaconda3 和PyCharm2016.3.3.

navicat远程连接阿里云ECS上的MYSQL报Lost connection to MySQL server at &#39;reading initial communication packet&#39;

问题现象 MySQL 远程连接报错:Lost connection to MySQL server at 'reading initial communication packet' 解决方案 1.检查是否有防火墙限制2.检查 MySQL 是否有访问权限 use mysql; Grant all privileges on *.* to 'root'@'%' identified by '密码' with grant option; flush privileges; 3.检查 my.ini 文

Qt 5.4.1下编译MySQL驱动,连接MySQL数据库

Qt安装在D:\Qt目录,Qt 5.4.1下连接MySQL数据库,发现会出现以下错误 QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL QMYSQL3 QODBC 到D:\Qt\Qt5.4.1\5.4\mingw491_32\plugins\sqldrivers目录下看看,发现是有mysql驱动的 Google了一下,据说是该驱动所满足的依赖性,不满足,需要重

Java连接mysql——Establishing SSL connection without server&#39;s identity verification is not recommended.

Establishing SSL connection without server's identity verification is not recommended. 出现这个错误的原因是因为mysql版本问题,不同的mysql对ssl使用情况不一样,尝试不采用ssl连接即可.操作方法如下. 正常情况下访问的url String url = "jdbc:mysql://192.168.61.123:3306/cpc"; 改正后的url String url = "jdb

Qt编译mysql驱动

Qt连接MySQL 分类: Qt 数据库 2013-02-27 20:57 1452人阅读 评论(0) 收藏 举报 一般情况下,qt只带了qsqlite4和qodbc两种驱动,如果在安装qt时,你没有添加qt -mysq参数,那么意味着,在你的程序中不能直接使用mysql数据库. 那么你就需要安装这个插件. 感谢jpzjpz提供的详细安装过程! 网址为:http://dev.wo.com.cn/bbs/viewthread.jsp?tid=140945&extra=page%3D1 我这里还是在

java mysql驱动

mysql驱动方式有三种, 1.第一种是先把jar包放在项目的目录下,通过添加jar包,是使用相对地址的,这样把项目复制到其它电脑也可以用 2.第二种方法是导入外部的jar包,是绝对地址,如果项目要复制到其它电脑又要重新导入 3.使用环境变量如何配置? --------------------- 参考文章:http://www.cnblogs.com/taoweiji/archive/2012/12/11/2812295.html --------------------------------

SQL Server 2012实施与管理实战指南(笔记)——Ch6连接的建立和问题排查

6.连接的建立和问题排查 会话的建立分成2个部分: 1.连接,即找到这个实例 2.认证,告诉sql server谁要连接 目录 6.连接的建立和问题排查... 1 6.1协议选择和别名... 1 6.1.1 服务器网络配置... 1 6.1.2 SQL Server Browser的作用... 1 6.1.3 客户端网络配置... 2 6.1.4 客户端网络连接选择机制... 2 6.2 连接失败检测步骤--命名管道... 2 6.3连接失败检测步骤--TCP/IP. 2 6.3.1 SQL S

安装好mysql后允许远程连接

1. 改表法 我就是使用这种方法!! (可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库里的 "user" 表里的 "host" 项,从"localhost"改称"%") c:/mysql/mysql server 5.1>mysql -u root -p 输入相应密码 mysql>use mys