Java 应用与 MySQL 的交互

1. MySQL驱动 数据库连接池

作为一个 Java工程师,不知道你有没有关注过一个问题,Java程序是如何与MySQL数据库进行交互的?

  1. MySQL驱动

应该大部分人都知道,我们首先需要配置一个 MySQL驱动,那MySQL驱动到底是个什么东西?
通俗一点解释,MySQL驱动 就是用来跟MySQL服务端进行通信,也就是创建网络连接,然后往服务器发送请求,执行SQL语句 等访问数据库的操作;

一般在项目中也就是这样一个maven依赖:

Xml
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.22</version>
</dependency>
  1. 数据库连接池

对于我们的Java系统,肯定不可能只跟MySQL创建一个连接的,如果只有一个的话,那就得单线程串行执行SQL语句了;

所以需要和MySQL服务端创建多个连接,但是每次创建和销毁一个数据库连接都是非常耗时的操作,那肯定就不能频繁的去创建和销毁了;

这种情况下,就引入了池化思想,也就是数据库连接池;在一个池子中维持多个数据库连接,让不同的线程需要执行SQL语句的时候,先去获取到一个连接,执行完成之后又将这个连接给放回池内;

常见的数据库连接池有:DBCP、C3P0、阿里的 Druid 这些;

这些池化的思想,在我们系统开发中很多地方都会遇到;如 线程池、内存池、HTTP连接池 等等……
可以扩展一下池化思想的一般作用

  • 资源复用:池中对象得到复用,避免了频繁的创建、释放带来的性能开销,减少内存碎片等;
  • 更快的响应速度:在要使用到对象时,直接从池中获取即可,不用在要用时才去等待创建;
  • 统一的对象管理:可以防止内存泄露,实现线程安全等;

一般来说,我们的系统是部署在Tomcat中的,或者现在的springboot内置的 Tomcat,一个Tomcat服务器中是有多个线程的(Tomcat8默认为200个线程),也就是说这些线程是可以同时接收多个请求,然后并发的处理的;

那把这些过程串联起来就是:

image-20220629170146290

  1. 部署在 Tomcat 中的Java应用,会通过数据库连接池创建一定数量的数据库连接;
  2. Tomcat 中也会有多个线程,可以同时接收用户的请求;
  3. 当有多个用户并发请求时,由Tomcat中的线程来处理这些请求;
    在要执行 SQL语句时,从 数据库连接池 中获取到跟 MySQL服务端的数据库连接,然后通过 MySQL驱动来向MySQL服务端发送请求,再由MySQL服务端来执行SQL语句;

    2. MySQL 架构设计

    上面说到通过 MySQL 驱动来发起请求由MySQL服务端执行 SQL 语句,那 MySQL 服务端是怎么执行的呢?

对于 MySQL服务端,其实也会维护一个连接池(连接管理器),用来管理多个客户端跟这个服务端创建的所有连接;
我们平常使用命令行来操作,来跟 MySQL服务端创建一个MySQL连接,一般也就是:

Bash
mysql -h$ip -P$port -u$user -p

执行之后,MySQL的连接管理器就会去验证你的账户密码和权限等;如果验证通过,就可以通过命令行来执行MySQL命令了;
这个客户端的连接,MySQL服务端会维护一定的时间长度(默认是8小时),也就是说如果你8小时客户端没有操作,连接管理器会自动将这个连接给断开(不然也是白白浪费资源维护这个连接,也就是要维护执行过程中使用到内存之类的资源);

当MySQL服务端接收到一个 SQL请求之后,也就是说从一个网络连接中接收到网络请求;那这个时候肯定就需要有一个线程来从网络连接中读取和解析请求;
也就是得到一个 SQL语句,转交给SQL接口去执行,完成底层数据的增删改查;

为了执行SQL语句,MySQL的 Server层,设计了如下的 组件:

image-20220629170240075

以这条 SQL 语句为例,解释一下:

select id, name, age from user where id = 1;
  • 解析器:对 SQL 语句做解析,也就是要让MySQL知道你这条 SQL语句,是要做什么;
    • 词法解析:识别出 SQL语句里面的字符串分别是什么,代表什么;比如这里就是:

      • select 表示这是一个查询语句;
      • user 表示 从user表中进行查询;
      • id = 1 表示查询 id为1 这行数据;
      • id、name、age 表示要从这行数据中提取这三个字段;
    • 语法分析:根据词法分析的结果,再判断你输入的这个 SQL 是否满足 MySQL的语法;

    • 也就是你在执行 sql 语句的时候,正常报出来的错误这些;

      Bash
      > 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 10' at line 1
      > 时间: 0.009s

      一般这个报错,都会提示你出现错误的位置,一般就关注 use near...

  • 优化器:当你的SQL语句中有多个索引,或者多个表关联查询时;优化器会决定使用哪个索引,或者决定各个表的连接顺序;也就是说优化器会决定一条 SQL 按照一个什么的步骤和顺序,去执行哪些操作;例如:

    MySQL
    select * from t1 join t2 where t1.c=10 and t2.d=20;

​ 既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2 里面 d 的值是否等于 20;
​ 也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10;
​ 这两种方式的执行结果是一样的,但是可能执行的效率会不同,所以优化器会根据执行成本来选择使用哪个方案;

  • 执行器:当通过优化器决定了怎么执行这条 SQL 时,就可以开始执行语句了;
    • 在执行之前,判断当前用户对于这个表是否有执行权限;如果有权限,才会打开这个表继续执行后面的操作;
    • 具体的执行,是通过执行引擎来实现的;也就是每个表在定义时,就指定了特定的执行引擎,然后 MySQL的Server 去调用具体执行引擎的接口,来执行这条 SQL语句;
    • 这里的执行引擎,一般默认就是 InnoDB,当然还有一些 MyIsam、Memory之类的;(这里就有一个面试题,InnoDB 和 MyIsam 的区别是什么,下去背一下就行了);
      对于不同引擎,他们的底层实现的存储结构或者存储方式这些都是不一样的;

也就是通过这些组件的配合,以这样一些流程来完成 执行一条 SQL 语句;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Java 中使用 MySQL 数据库,需要使用 JDBC(Java Database Connectivity) API。下面是一个简单的 Java 程序,演示如何连接 MySQL 数据库并执行一些基本的查询操作: ```java import java.sql.*; public class MySQLExample { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { // 连接 MySQL 数据库 conn = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "username", "password"); // 创建 SQL 语句 String sql = "SELECT * FROM customers"; // 创建 Statement 对象 stmt = conn.createStatement(); // 执行 SQL 查询 ResultSet rs = stmt.executeQuery(sql); // 处理查询结果 while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String address = rs.getString("address"); System.out.println("ID: " + id + ", Name: " + name + ", Address: " + address); } } catch (SQLException e) { e.printStackTrace(); } finally { // 关闭连接和 Statement 对象 try { if (stmt != null) stmt.close(); if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } ``` 在上面的示例中,我们使用 `DriverManager.getConnection()` 方法连接 MySQL 数据库,并使用 `Statement` 对象执行 SQL 查询。我们还遍历查询结果集并打印每个行的数据。最后,我们关闭连接和 Statement 对象。 请注意,上述示例仅用于演示目的。在实际应用中,应该使用 `PreparedStatement` 对象来执行 SQL 查询,以避免 SQL 注入攻击。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值