`
wu_quanyin
  • 浏览: 204690 次
  • 性别: Icon_minigender_1
  • 来自: 福建省
社区版块
存档分类
最新评论

Mysql JDBC驱动源码分析(获取连接)二

阅读更多

setReadonly(true)

 概念:从这一点设置的时间点开始到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)

应用场合:

如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性; 

如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。

【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】

怎样设置:

对于只读查询,可以指定事务类型为readonly,即只读事务。

由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。

 

 

当驱动加载完毕后,接下来就是怎样去获取一个连接

 

Drivermanager.getConnection(url,name,password)

 跟踪代码执行到以下一步

 

 private static Connection getConnection(
	String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
	java.util.Vector drivers = null;
        /*
	 * When callerCl is null, we should check the application's
	 * (which is invoking this class indirectly)
	 * classloader, so that the JDBC driver class outside rt.jar
	 * can be loaded from here.
	 */
	synchronized(DriverManager.class) {	 
	  // synchronize loading of the correct classloader.
	  if(callerCL == null) {
	      callerCL = Thread.currentThread().getContextClassLoader();
	   }    
	} 
	 
	if(url == null) {
	    throw new SQLException("The url cannot be null", "08001");
	}
    
	println("DriverManager.getConnection(\"" + url + "\")");
    
	if (!initialized) {
	    initialize();
	}

	synchronized (DriverManager.class){ 
            // use the readcopy of drivers
	    drivers = readDrivers;  
        }

	// Walk through the loaded drivers attempting to make a connection.
	// Remember the first exception that gets raised so we can reraise it.
	SQLException reason = null;
	for (int i = 0; i < drivers.size(); i++) {
	    DriverInfo di = (DriverInfo)drivers.elementAt(i);
      
	    // If the caller does not have permission to load the driver then 
	    // skip it.
	    if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
		println("    skipping: " + di);
		continue;
	    }
	    try {
		println("    trying " + di);
                //在注册的驱动中得到相应的连接
		Connection result = di.driver.connect(url, info);
		if (result != null) {
		    // Success!
		    println("getConnection returning " + di);
		    return (result);
		}
	    } catch (SQLException ex) {
		if (reason == null) {
		    reason = ex;
		}
	    }
	}
    
	// if we got here nobody could connect.
	if (reason != null)    {
	    println("getConnection failed: " + reason);
	    throw reason;
	}
    
	println("getConnection: no suitable driver found for "+ url);
	throw new SQLException("No suitable driver found for "+ url, "08001");
    }

 进入com.mysql.jdbc.Driver下connect(url,info)方法NonRegisteringDriver

 

 

public java.sql.Connection connect(String url, Properties info)
			throws SQLException {
		if (url != null) {
			if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {//负载均衡的配置
				return connectLoadBalanced(url, info);
			} else if (StringUtils.startsWithIgnoreCase(url,
					REPLICATION_URL_PREFIX)) {//复制
				return connectReplicationConnection(url, info);
			}
		}

		Properties props = null;

		if ((props = parseURL(url, info)) == null) {
			return null;
		}

		if (!"1".equals(props.getProperty(NUM_HOSTS_PROPERTY_KEY))) {
			return connectFailover(url, info);
		}
		
		try {//初始化链接
			Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(
					host(props), port(props), props, database(props), url);

			return newConn;
		} catch (SQLException sqlEx) {
			// Don't wrap SQLExceptions, throw
			// them un-changed.
			throw sqlEx;
		} catch (Exception ex) {
			SQLException sqlEx = SQLError.createSQLException(Messages
					.getString("NonRegisteringDriver.17") //$NON-NLS-1$
					+ ex.toString()
					+ Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$
					SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null);
			
			sqlEx.initCause(ex);
			
			throw sqlEx;
		}
	}
 

 对com.mysql.jdbc.JDBC4Connection的初始化

 

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);
	}

 进入Jdbc4Connection的代码跟踪

 

 

protected ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info,
			String databaseToConnectTo, String url)
			throws SQLException {
		this.charsetToNumBytesMap = new HashMap();
	
		this.connectionCreationTimeMillis = System.currentTimeMillis();
		this.pointOfOrigin = new Throwable();

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

		// Stash away for later, used to clone this connection for Statement.cancel
		// and Statement.setQueryTimeout().
		//
		
		this.origHostToConnectTo = hostToConnectTo;
		this.origPortToConnectTo = portToConnectTo;
		this.origDatabaseToConnectTo = databaseToConnectTo;

		try {
			Blob.class.getMethod("truncate", new Class[] {Long.TYPE});
			
			this.isRunningOnJDK13 = false;
		} catch (NoSuchMethodException nsme) {
			this.isRunningOnJDK13 = true;
		}
		
		this.sessionCalendar = new GregorianCalendar();
		this.utcCalendar = new GregorianCalendar();
		this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));

		this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME, getExceptionInterceptor());

		// We store this per-connection, due to static synchronization
		// issues in Java's built-in TimeZone class...
		this.defaultTimeZone = Util.getDefaultTimeZone();
		
		if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) {
			this.isClientTzUTC = true;
		} else {
			this.isClientTzUTC = false;
		}

		this.openStatements = new HashMap();
		
		if (NonRegisteringDriver.isHostPropertiesList(hostToConnectTo)) {
			Properties hostSpecificProps = NonRegisteringDriver.expandHostKeyValues(hostToConnectTo);
			
			Enumeration<?> propertyNames = hostSpecificProps.propertyNames();
			
			while (propertyNames.hasMoreElements()) {
				String propertyName = propertyNames.nextElement().toString();
				String propertyValue = hostSpecificProps.getProperty(propertyName);
				
				info.setProperty(propertyName, propertyValue);
			}
		} else {
		
			if (hostToConnectTo == null) {
				this.host = "localhost";
				this.hostPortPair = this.host + ":" + portToConnectTo;
			} else {
				this.host = hostToConnectTo;
				
				if (hostToConnectTo.indexOf(":") == -1) {
					this.hostPortPair = this.host + ":" + portToConnectTo;
				} else {
					this.hostPortPair = this.host;
				}
			}
		}

		this.port = portToConnectTo;

		this.database = databaseToConnectTo;
		this.myURL = url;
		this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);
		this.password = info
				.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);

		if ((this.user == null) || this.user.equals("")) {
			this.user = "";
		}

		if (this.password == null) {
			this.password = "";
		}

		this.props = info;
		
		
		
		initializeDriverProperties(info);
		
		
		try {   //获取数据库的信息
			this.dbmd = getMetaData(false, false);
			initializeSafeStatementInterceptors();
                        //======================================创建远程IO连接
			createNewIO(false);
			unSafeStatementInterceptors();
		} catch (SQLException ex) {
			cleanup(ex);

			// don't clobber SQL exceptions
			throw ex;
		} catch (Exception ex) {
			cleanup(ex);

			StringBuffer mesg = new StringBuffer(128);

			if (!getParanoid()) {
				mesg.append("Cannot connect to MySQL server on ");
				mesg.append(this.host);
				mesg.append(":");
				mesg.append(this.port);
				mesg.append(".\n\n");
				mesg.append("Make sure that there is a MySQL server ");
				mesg.append("running on the machine/port you are trying ");
				mesg
						.append("to connect to and that the machine this software is "
								+ "running on ");
				mesg.append("is able to connect to this host/port "
						+ "(i.e. not firewalled). ");
				mesg
						.append("Also make sure that the server has not been started "
								+ "with the --skip-networking ");
				mesg.append("flag.\n\n");
			} else {
				mesg.append("Unable to connect to database.");
			}

			SQLException sqlEx = SQLError.createSQLException(mesg.toString(),
					SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, getExceptionInterceptor());
			
			sqlEx.initCause(ex);
			
			throw sqlEx;
		}
	}
 

 

 

 

 

 

分享到:
评论

相关推荐

    sharding-jdbc-1.5.1:sharding-jdbc原始码解析

    分片JDBC-分片数据库和表的JDBC驱动程序 概述 分片JDBC是JDBC的扩展,提供了诸如分片,读/写拆分和BASE事务之类的分布式功能。 特征 1.分片 分布式数据库中支持的聚合功能,分组依据,排序依据和限制SQL。 支持联接...

    MySQL 5.1中文手冊

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装...

    MySQL 5.1官方简体中文参考手册

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装...

    MySQL 5.1参考手册

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装...

    MySQL 5.1参考手册中文版

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过...

    MySQL 5.1参考手册 (中文版)

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装...

    mysql5.1中文手册

    使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 ...

    MYSQL中文手册

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过...

    mysql官方中文参考手册

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装...

    MySQL5.1参考手册官方简体中文版

    2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装...

    xalanjava源码-venice:来自原始威尼斯商人贸易软件的个人叉

    java源码威尼斯商人,0.752 beta 26/December/2018 版权所有 (C) 2003-19,Andrew Leppard (andrew venice org nz) 有关许可条款,请参阅 COPYING.txt。 1 简介 感谢您试用威尼斯商人(威尼斯)。 威尼斯是一个股票...

    百度地图开发java源码-EchartDemo:echart的案例,使用javaweb后端技术,通过ajax异步刷新更新数据

    百度地图开发java源码 EchartDemo 项目介绍 基于java web和echarts的数据可视化项目 主要分析浙江省各市区的gdp和固定资产投资、以及房产数据,数据源,数据经过整理后插入数据库中。...#JDBC驱动建立连接时附带的连

    毕业设计:Java项目之jsp学生社团管理系统(源码 + 数据库 + 说明文档)

    2.2.5 JDBC驱动介绍 4 2.2.6软硬件需求 5 第3章 软件需求分析 5 3.1功能需求 5 3.1.1功能划分 5 3.1.2功能描述 6 3.2外部接口需求 6 3.2.1用户界面 6 第4章 软件概要设计 7 4.1总体设计 7 4.1.1处理流程 7 4.1.2总体...

    JAVA上百实例源码以及开源项目源代码

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    JAVA上百实例源码以及开源项目

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    图书馆管理系统(Java) 优秀毕业设计论文+软件设计源码.zip

    本系统中通过JDBC驱动和数据库进行无缝连接,后端的数据库是mysql,也是一个开源的数据库系统,该数据库具有较高的完整性,一致性和安全性。 关键词:图书管理;信息管理;jsp;struts 绪 论 1.1毕业设计主要任务 ...

Global site tag (gtag.js) - Google Analytics