热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mysql和oracle驱动建立连接的过程

我们知道所有的驱动程序其实都是实现相同的JDK接口来连接数据库。这些接口其实就是JDBC接口。那我们就从JDBC连接来看mysql驱动是怎么实现这些接口来连接数据库的。首先写了

我们知道所有的驱动程序其实都是实现相同的JDK接口来连接数据库。这些接口其实就是JDBC接口。

那我们就从JDBC连接来看mysql驱动是怎么实现这些接口来连接数据库的。

首先写了一个简单的数据库连接程序,和mysql 建立连接

当前使用的mysql驱动是 mysql-connector-java-8.0.22.jar、jdk8.

Connection cOnnection= DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatisplus?serverTimezOne=Asia/Shanghai","root","123456") ;
       Statement statement =  connection.createStatement() ;
       ResultSet resultSet = statement.executeQuery("select * from user") ;
       while (resultSet.next()){
           System.out.println((resultSet.getString("name")));
       }

 

首先我们的mysql驱动类 com.mysql.cj.jdbc.Driver通过实现 java.sql.Driver ,会在应用启动时把驱动注册到DriverManager当中去。这也就是说,当我们以后需要自己开发一个驱动时,也是一样的去实现 java.sql.Driver 。

 

 

DriverManager 内部是维护了一个 list来存储这些注册的驱动,以供后续使用的。

// List of registered JDBC drivers
private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList<>();

 

 

 然后我们再看DriverManager怎么去getConnection的。我们可以看到getConnection里面会有一个遍历所有的Drivers,去建立连接。

同样的我们可以看到mysql建立连接的实现类是NonRegisteringDriver,接下来看下这里面是怎么建立连接的。

 

 

 那我们可以看到 NonRegisteringDriver 的connect方法里面就是根据不同的连接类型 建立connection实例。

这些连接类型是定义在ConnectionUrls里面的一个枚举类  有jdbc:mysql、jdbc:mysql:loadbalance等等,就是根据我们的url来区分。

 

 

 public Connection connect(String url, Properties info) throws SQLException {
        try {
            try {
                if (!ConnectionUrl.acceptsUrl(url)) {
                    return null;
                } else {
                    ConnectionUrl cOnStr= ConnectionUrl.getConnectionUrlInstance(url, info);
                    switch(conStr.getType()) {
                    case SINGLE_CONNECTION:
                        return ConnectionImpl.getInstance(conStr.getMainHost());
                    case FAILOVER_CONNECTION:
                    case FAILOVER_DNS_SRV_CONNECTION:
                        return FailoverConnectionProxy.createProxyInstance(conStr);
                    case LOADBALANCE_CONNECTION:
                    case LOADBALANCE_DNS_SRV_CONNECTION:
                        return LoadBalancedConnectionProxy.createProxyInstance(conStr);
                    case REPLICATION_CONNECTION:
                    case REPLICATION_DNS_SRV_CONNECTION:
                        return ReplicationConnectionProxy.createProxyInstance(conStr);
                    default:
                        return null;
                    }
                }
            } catch (UnsupportedConnectionStringException var5) {
                return null;
            } catch (CJException var6) {
                throw (UnableToConnectException)ExceptionFactory.createException(UnableToConnectException.class, Messages.getString("NonRegisteringDriver.17", new Object[]{var6.toString()}), var6);
            }
        } catch (CJException var7) {
            throw SQLExceptionsMapping.translateException(var7);
        }
    }

 那我们从最简单的 SINGLE_CONNECTION类型看 即我们url是以 jdbc:mysql开头的。实现也是很简单就是new ConnectionImpl 返回connection实例


case SINGLE_CONNECTION:
    return ConnectionImpl.getInstance(conStr.getMainHost());

 第二 看下常见的负载均衡连接 ,loadbalance连接时通过反射方式生成connection实例的。

case LOADBALANCE_CONNECTION:
                    case LOADBALANCE_DNS_SRV_CONNECTION:
                        return LoadBalancedConnectionProxy.createProxyInstance(conStr);

我们可以看到LoadBalanceProxy来实现的,通过java 反射,java.lang.reflect.Proxy.newProxyInstance ,通过构造器Constructor 来生成实例对象。

真正一些策略性的选择在 LoadBalanceProxy的构造方法中可以看到,默认是随机策略 random

public static LoadBalancedConnection createProxyInstance(ConnectionUrl connectionUrl) throws SQLException {
    LoadBalancedConnectionProxy connProxy = new LoadBalancedConnectionProxy(connectionUrl);
    return (LoadBalancedConnection)Proxy.newProxyInstance(LoadBalancedConnection.class.getClassLoader(), INTERFACES_TO_PROXY, connProxy);
}

如下图我们可以看到构造方法中几种loadbalance策略选择

RandomBalanceStrategy

BestResponseTimeBalanceStrategy

ServerAffinityStrategy

 

 第三种可以看到有主备的策略,跟loadbalance一样通过 java 反射,java.lang.reflect.Proxy.newProxyInstance ,通过构造器Constructor 来生成实例对象。


case REPLICATION_CONNECTION:
case REPLICATION_DNS_SRV_CONNECTION:
    return ReplicationConnectionProxy.createProxyInstance(conStr);

 所以我们可以直接看下 ReplicationConnectionProxy 代理的实现方法。我们可以看到是优先masterConnection,

master没有再选择slaveConnection,this.currentCOnnection= this.slavesConnection;

this.currentCOnnection= this.initializeMasterConnection();

 

try {
            this.currentCOnnection= this.initializeMasterConnection();
        } catch (SQLException var10) {
            exCaught = var10;
        }

        if (this.currentCOnnection== null) {
            if (!this.allowMasterDownConnections || this.slavesCOnnection== null) {
                if (this.connectionGroup != null) {
                    this.connectionGroup.handleCloseConnection(this.thisAsReplicationConnection);
                }

                if (exCaught != null) {
                    throw exCaught;
                } else {
                    throw SQLError.createSQLException(Messages.getString("ReplicationConnectionProxy.initializationWithEmptyHostsLists"), "S1009", (ExceptionInterceptor)null);
                }
            }

            this.readOnly= true;
            this.currentCOnnection= this.slavesConnection;
        }

 至此我们就能生成connection实例返回,当然这只是一个很粗的链路,里面很多细节还是需要自己亲自看看源码是怎样的。

当然我演示的代码在我的github 仓库里面有可以下载

https://github.com/xusyPersonal/springboot-mybatis-plus-demo.git  ,

这个项目是我使用springboot集成mybatis-plus的,可以简单用来学习。今天演示的连接数据库是这个测试类 MysqlConnectionTest,欢迎下载!

 


推荐阅读
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • Amoeba 通过优化 MySQL 的读写分离功能显著提升了数据库性能。作为一款基于 MySQL 协议的代理工具,Amoeba 能够高效地处理应用程序的请求,并根据预设的规则将 SQL 请求智能地分配到不同的数据库实例,从而实现负载均衡和高可用性。该方案不仅提高了系统的并发处理能力,还有效减少了主数据库的负担,确保了数据的一致性和可靠性。 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • MySQL Decimal 类型的最大值解析及其在数据处理中的应用艺术
    在关系型数据库中,表的设计与SQL语句的编写对性能的影响至关重要,甚至可占到90%以上。本文将重点探讨MySQL中Decimal类型的最大值及其在数据处理中的应用技巧,通过实例分析和优化建议,帮助读者深入理解并掌握这一重要知识点。 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 为了确保数据库的高效运行,本文介绍了一种方法,通过编写定时任务脚本来自动清理 `order` 表中状态为 0 或为空的无效订单记录。该脚本使用 PHP 编写,并设置时区为中国标准时间,每 10 分钟执行一次,以保持数据库的整洁和性能优化。此外,还详细介绍了如何配置定时任务以及脚本的具体实现步骤。 ... [详细]
  • 在Linux系统中避免安装MySQL的简易指南
    在Linux系统中避免安装MySQL的简易指南 ... [详细]
  • 类加载机制是Java虚拟机运行时的重要组成部分。本文深入解析了类加载过程的第二阶段,详细阐述了从类被加载到虚拟机内存开始,直至其从内存中卸载的整个生命周期。这一过程中,类经历了加载(Loading)、验证(Verification)等多个关键步骤。通过具体的实例和代码示例,本文探讨了每个阶段的具体操作和潜在问题,帮助读者全面理解类加载机制的内部运作。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • PHP中元素的计量单位是什么? ... [详细]
  • 提升MySQL数据库架构性能的策略与方法
    为了提升MySQL数据库架构的性能,本文探讨了多种策略与方法。首先,分析了影响数据库性能的关键因素,并详细阐述了数据库结构优化的重要性。接着,介绍了数据库设计的基本步骤,包括第一、第二和第三范式的应用,以及反范式化设计的场景。此外,还讨论了数据库物理设计的关键要素,如表定义、索引设计和存储引擎选择,以确保高效的查询响应和数据管理。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有