MySQL Java 开发实战|学习笔记

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 快速学习 MySQL Java 开发实战。

开发者学堂课程【MySQL 实战进阶MySQL Java 开发实战】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/852/detail/14061


MySQL Java 开发实战

 

内容介绍:

一、深入浅出 ORM 框架 MyBatis

二、连接池框架剖析和最佳实践

三、Java 应用性能问题诊断技巧

 

 

一、深入浅出 ORM 框架 MyBatis

1、为什么要选 MyBatis

直接用 JDBC 跟数据库进行查询的好处是比较简单直接,缺点是开发效率比较低。如果用 JDBC 写程序需要大量手工写代码的工作,而且有很多代码重复,后来逐渐演化出 ORM 框架。

ORM 框架最早期有 Hibernate、JPA 的规范。Hibernate 是一个比较完善的 Hibernate框架,能够屏蔽底层数据库的差异,自动根据 HQ 语言生成对应数据库的不同数据库方言,缺点是对关联查询的知识不是很友好,同时它的动态 SQL 的能力也不是很好,很难写出高效的 SQL。

在国内,目前流行 MyBatis,它比较轻量级,同时对动态 SQL 以及关联查询的支持都会比较好,缺点就是它绑定了一个 DB,要手写 SQL 还有动态空间,很难从一个 DB 自由的切换到另外一个 DB。

2、MyBatis 基本概念介绍

MyBatis 主要分为三层,第一层是接口层,第二层是核心层,第三层是基础层。

image.png

(1)接口层

接口层主要通过提供的 API 来对数据库进行增、删、改、查。

(2)核心层

核心层有 SQL 预处理、SQL 执行和结果映射。SQL 预处理对代码里的一些变量进行绑定以及动态 SQL 的生产;SQL 执行把生产的 SQL 通过 JDBC 的驱动传到对应的 DB 去执行,而且负责网络通信的部分;结果映射把数据库返回的结果从关系型的数据转换成 Java 里的对象数据,就是结果集映射。

(3)基础层

基础层有日志、事务管理、缓存、连接池、动态代理、配置解析。日志主要是做框架里的一些日志的输出以及 SQL 语句的输出;事务管理主要是对 JDBC 的数据库的事务做一些管理,目前事务管理主要是交给 Spring 容器管理;缓存,MyBatis、Hibernate 都提供一级缓存、二级缓存,它能够把结果集缓存在 jvm 的堆内存的内部,好处是它比较快,缺点是它会占用堆内存,所以有条件的情况下,建议多使用分布式的缓存;连接池,MyBatis 也提供连接池的功能,能够加速查询、能够提高性能,但很多时候还是会选择市面上更成熟更专业的一些连接池;动态代理是在用 MyBatis 去编程时,有基于注解的方式,有基于 xml 配置的方式,但核心来说都是通过 mapper 接口去执行数据库的查询,而 mapper 接口本身是没有实现的,它的实现就是在 xml 或者在注解里配置的 SQL 语句会在运行时收藏代理,去第二个 mapper 接口时,它会把它转换成为实际的 SQL 语句;配置解析,MyBatis 里存在大量的配置,需要配置解析模块读取 xml 的配置,并把它映射为配置属性。

3、MyBatis 从0开始搭建工程

image.png

(1)技术选型

现在最主流的是跟 spring 框架做结合,还有底下有连接池也要去做结合,这里的选型就是使用最新的 spring-boot2,我们去开发一个 web 工程,可以选择 spring-webmvc 框架,持久层或者 ORM 映射层,可以选用 MyBatis 框架,在连接池可以选择 HikariCP,也可以选择其他的连接池,这里是用 HikariCP,HikariCP 是 spring-boot2默认的连接池,数据库推荐大家使用 RDS MySQL,这是国内比较流行的一个数据库。

有了以上选型,你可以在 spring 的官方网站上面,链接 https://spring.io/quickstart,通过链接填入相关的信息可以生成一个框、一个项目、一个模板,模板下载下来之后,在 ID 里打开,导入项目,就有开始工作的项目模板。

(2)项目依赖

第一部分要依赖 spring boot starter,作用是自动管理 spring boot,开始做 spring boot项目时一些默认的依赖都已经集成到 start 里,还用到 spring 的 webmvc 用的是最新的2.4.1版本。除此以外,用了 MyBatis 还要依赖 MyBatis 的 starter,需要注意 MyBatis 没有 spring 官方的 starter,而是 MyBatis 的社区提供一个 MyBatis 的spring boot starter。还需要依赖 JDBC 的 MySQL 版的实现,就是 MySQL connector Java。

JDBC 是一套规范、一套 API,具体的实现是由各个数据库的厂商去实现,比如 MySQL 或者 SQL server,都会有对应的实现,我们还依赖 spring boot starter 测试框架测试这部分,为了减少代码量,还用到了 null boot。

(3)工程结构

在工程结构里,从下往上看。有控制器层 Controller,有一个自己的控制器。有 mapper 层,主要是数据库的增、删、改、查的接口。有 order 层,主要是在 Java 里的对象的类的定义。

还有 service 层,service 层又有 API 层和 implementation 层,API 层主要是接口的定义,implementation 主要是对接口的实现,在接口里面会去调用 mapper 层,或者是调用一些业务层的一些东西来实现业务逻辑的组装和编排。

最底下是 Java 应用的启动类,是启动的入口。这次选择是用 xml 的方式配置 MyBatis,在 resource 目录里需要增加 mapper 的目录,mapper 目录里放入 mapper 文件。

底下是 spring、logo4j、MyBatis 的配置文件,但 MyBatis 配置的也可以通过编程的方式去实现,最底下有 pom 文件。到这里为止,一个从0开始搭建的 MyBatis 的工程就完成了。

工程启动之后,在浏览器里输入链接 http://ocalhost:8001/query? Name = yanglong,端口、路径都是自己定义,可以验证工程是否正常运作。

 

二、连接池框架剖析和最佳实践

1、为什么要用连接池

首先,如果不用连接池,那么每次查询都需要去建立连接,建立连接有两层的握手,第一层是 TCP 层的握手,第二层是 MySQL 协议里的握手,这两层协议大概需要有多个 TCP 的数据包,这些都需要时间。除此以外,在数据库内部还需要一些处理,建立连接是比较费时间的操作。

第二,当代应用服务器很多时候是很多台,数据库的服务器相比之下可能会少一些,应用服务器很多会在业务流量的高峰期时存在很多 DB 的连接,而 DB 能够承载的连接数是有限的,如果不用连接池,那么连接的数量不受控制,可能会导致 DB 的性能严重的降低,就意味着每次去执行 SQL 语句都需要去创建 TCP 连接和关闭 TCP连接,而关闭的动作一般都是在应用端完成,会导致应用服务器上会存在较多的 TIME_WAIT 状态的 TCP 连接,TIME_WAIT 状态的连接数达到一定数量之后,可能会引起应用的问题,比如端口不够用。

用连接池会有什么收益?

第一,它不用每次都去建立连接,而是直接从连接池里取连接,性能会更好。

第二,连接池可以控制连接的数量,当连接出现问题的时候,连接池能够自动探测连接是否存活,如果连接中断,连接池会自动重建,比如应用使用了 RDS 的 MySQL,可能需要对 MySQL 的实例进行配置变更,比如升规格,提高磁盘空间,有时候遇到一些奇怪的问题或者压力很大时希望重启 MySQL,这时都会导致应用跟 MySQL 之间的连接中断,如果有了连接池,就能自动处理好这些问题,不会导致应用里去拿一个连接但这个连接是不可用的问题。

除此以外,连接池能够对连接进行灵活的管理、做很多配置,对连接池的状态做监控,看到连接池里的各种连接的数量和一些性能指标。

image.png

2、连接池架构

连接池最顶层是接口层,下面是核心层,最底下是基础层。

image.png

(1)接口层

接口层就是比如 MyBatis 需要从连接池里连接 get connection,当连接用完后,它需要把连接关闭,就会调用连接的 close,就是连接的归还。

(2)核心层

核心层主要负责并发控制、连接控制、异常处理。并发控制,连接池里的连接数量是有限的,但是应用里的线程数量可能会多于连接池的连接数量,当连接池里的连接都已经处于活跃状态的时候,下一个请求想要继续得到连接就要等待,数量是有限的,需要排队,这是一种情况。

第二个就是同一个连接不能给分配给多个线程,因为分配给多个线程后可能会开启事务,对同一个连接进行多次开启事务可能会引起事务的混乱。连接控制,就是需要去动态地调整连接池的大小,同时,也要让连接池保证连接数量在希望的范围内。异常处理,存在一些情况,比如数据库的重启,网络的中断,或者连接里发生协议层、引擎层上的错误,这个连接不能再使用了,这时候连接池会自动去处理这些问题,把连接关掉。

(3)基础层

基础层有配置管理、监控、定时任务、日志、字节码操纵。配置管理,连接池里有很多配置项,最常用的不多,但它可配置的点很多,这些需要进行解析和管理。连接池运行时需要做统计和监控,最好能够提供查看的页面。定时任务,连接池里连接的数量超过一定程度的时候,比如空闲连接超过一定数量,要对空闲连接做释放,这些都是通过定时任务完成。字节码操纵,在 Java 框架里会存在大量的字节码操纵,它会去动态的生成代理,增加业务逻辑。

3、druid 最佳实践-参数配置

比较常用的参数配置:

image.png

max-active,指的是连接池里允许的最大活跃的连接数,连接池的连接数不会超过这个数量,这个值需要根据应用的实际情况进行调整。

min-idle,指的是如果应用里有很多连接,比如有50个连接,这些连接现在没有使用了,这时可以让连接池关掉多余的只保留必要的空闲连接,比如说保留10个,这时候可以配 min-idle = 10,连接池会把剩下的40个多余的连接关闭,可以节省数据库的资源。

max-wait,这不是建立连接时的等待时间,而是应用层通过调用连接池的 API 获取连接的时候等待的时间,比如连接池里的连接已经被应用占用,这时并发的连接想获得连接就要等待,max-wait 就是指应用的线程等待的超时时间,一般可以配在几秒钟,比如1秒、3秒、4秒、5秒这样一个范围,根据业务应用的实际情况进行判定。

validation-query,连接池探测当前连接是否健康的 SQL 语句,比如 the read,最新版的 JDBC 驱动会调用 ping 的命令,如果 JDBC 比较新,就不会发 SQL 语句过去,而是发 ping 的命令。

validation-query-timeout,指的是上面探测的超时时间。

test-on-borrow,是指连接从连接池里取出来的时候,连接池是否需要对连接进行健康探测,这个选项以及 test-on-return 建议是关闭,如果打开这两个选项,它会带来性能的损失。

test-while- idle,建议打开,配置成 true,这个值是控制当连接处于空闲状态的时候,是否需要去检测连接的健康状态。

time-between-eviction-runs-milis,指的是触发空闲连接健康探测的时间阈值,需要跟 test-while- idle 结合起来,可以配置超时,也可以不配置。

remove-abandoned,是否需要开启泄露连接的强制回收,默认是 false,如果应用存在接连泄露的情况,这时可以选择打开,但不建议在线上的服务器长时间打开,因为打开以后,每次去获取连接的时候,它都需要记录现场的执行堆栈,以便出现连接泄漏的时候能够把堆栈打印出来,便于排查问题。所以不建议开启,除非需要在紧急情况下排查问题,或者在开发环境进行问题的定位。

remove- abandoned-timeout,指的是强制回收的触发时间阈值,比如连接交给了应用程序的线程,如果超过十秒钟还没有归还给时,就会触发对连接的强制回收,可以去配置,建议不要配置太短,因为线程里业务可能存在需要长时间的使用一个连接,超时时间要比业务上实际合理的时间要高,注意 remove-abandoned-timeout 配置单位是秒。

log- abandoned,指的是当一个连接被探测为连接泄露并且强制关闭的时候,是否要在日志里输出获取连接的线程的堆栈,跟 remove- abandoned 结合起来,如果需要定位,建议把 log- abandoned 开成 true,能够在日志里看到具体的堆栈。

当开启了空闲连接的健康探测的时候,在 druid 的源码内部它会触发怎样的逻辑。

首先,入口是比如 MyBatis 去找 druid 去拿连接的时候,去 get connection,这里是一个循环,在循环里面,它会从连接池里取一个空闲的连接,当探测空闲连接的健康的开关开启的时候,druid 就会检测连接的空闲时间有没有超过下面配置的阈值,如果超过了,它就会发起连接的健康探测,如果探测出来连接有问题,它就会直接把连接关闭,而且它是在一个 FULL 循环里面,它会回到 FULL 循环的开头,从连接池里再拿一个连接,循环反复,直到拿到一个可用的连接,或者连接池里的所有连接都有问题的时候,它就会重新创建连接。

4、druid 最佳实践-监控

在 spring 的配置里开启 druid 的监控选项,开启完后它就会在内部维护一个状态,同时,有一个基于 web 的管理页面,可以监控连接池的运行状态,如图,

 image.png

可以查看连接池的配置参数、版本,也可以查看连接池里的连接数、 SQL 监控、API,通过什么样的 API 可以拿到这些监控数据,除此以外,还可以通过 JMX 直接连到应用内部去看 druid 内部 JMX 对象里面的一些属性。

有些参数是可以修改的,有些参数是直接能看的,还有一些操作,一些 API 可以调用,所以 JMX 是比较强大的。

5、druid 最佳实践-连接泄露诊断

 image.png

一般泄露的现象是正常请求拿不到连接产生报错或者异常,同时应用的响应时间会增大,应用会出现不可用的这种情况。
原因是连接被取出后没有正常归还,导致连接长时间被占用但没有使用,这一般是代码的问题。

怎么去解决呢?一般来说,可以开启连接池的泄露诊断,找到根本原因后,可以修改代码解决问题。下面两行日志就是连接池里的连接全部被应用取走后,新的应用、新的请求去取连接的时候得不到连接,会超时报错。

com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 1000 2,active1, maxActive1, creating0

at com.alibaba.druid.pool.DruidDataSource.getConnection Internal(DruidDataSource.java:1738) ~[druid-1.2.4.jar:1.2.4]

一旦连接池里的连接全部泄露,后续的所有请求都拿不到连接,都会报这个错,可以通过在 spring 的配置文件里增加 druid 连接泄露的参数,开启完后,当出现连接泄露的时候,druid 会在日志里打印出被泄露出去的线程,被泄露出去的连接在取得连接的一个线程的堆栈,可以直接看到是什么样的业务代码在什么情况下取得连接而没有归还,有助于定位问题,同时,也可以在 druid 的监控页面上看到这个堆栈。

 

三、Java 应用性能问题诊断技巧

Java 应用系统主要分为内存问题、CPU 问题和网络问题。

1、内存

 image.png

内存问题的一般的现象是在日志里会报错,报 OutOfMemoryError: Java heap space 这个错误,看到这个错误的第一反应是堆内存耗尽,通过工具去查看 GC 情况,会发现应用里 GC 非常多,频繁的 FULL GC。

原因一般是内存泄露,或者是堆大小配置的不合理,就是配的太小了,业务需要更大的堆。

解决办法,需要通过一些工具定位出根本原因,比如到底是内存泄露还是堆大小配置的不合理,会用到以下工具:jvisualvm、jstat、jmap、mat。

下面这段日志是当出现堆内存耗尽的时候,Java 出来的一些错误,

java.lang.OutOfMemoryError. Java heap space

at java.util.Arrays.copyOfRange(Arrays.java:3664)~[na:1.8. 0. 271]

atjava.lang.StringBuffertoString(StringBuffer.java:669) ~[na:1.8.0 271]

at com.aliyunjavards.controller.MyController.genString (MyController. java:74) ~[classes!/:0.0.1-SNAPSHOT]

at com.aliyunjavards controllr.MyControllerleakMem (MyController java:63) ~[classes!/:0.0.1-SNAPSHOT]

at sun.reflect.NativeMethodAccessorlmplinvoke0(Native Method) ~[na: 1.8.0. 271]

底下的是如果内存真的耗尽的时候,这个应用也必然会出现频繁的 FULL GC,

image.png

通过上图可以看到,在三秒钟里出现了多次 FULL GC,可以说 FULL GC已经非常频繁。那么怎么去诊断内存的问题?第一种方法可以用JMX。

(1)内存-JMX

用 JMX 的前提是应用要打开 JMX,通过-D 开头的4个启动参数可以打开 JGX,

java

-Xmx512m

-Djava.rmi.server.hostname=192.168.56.102

-Dcom.sun.management.jmxremote. port= 6666

-Dcom.sun.managementjmxremote.ssl=false

-Dcom.sun.managementjmxremote .authenticate=false

jar targetjava-rds-0.0.1-SNAPSHOTjar

打开后进行远程连接,连上去之后可以看到最大堆的大小,以及实际已经使用的情况。

image.png

同时,通过 JMX 对堆进行一个 Dump,它会把这个文件放在 JVM 运行的所在的主机的对应目录上去。

image.png

(2)内存-jmap

第二个方法,在服务器上,没有图形界面,只能通过命令行去操作的时候怎么办?可以用 jmap 命令,通过 jmap-heap 2780 就是 JVM 的进程号。

 image.png

可以看到,JVM 的堆的最大大小是512兆,同时也可以看到老年代的使用情况是78%,是比较高了。通过命令把 JVM 的堆内存 dump 到文件里,便于做后续的分析,通过命令 Dumping heap to /share/jvm. hprof -,它会提示正在进行 dump,dump 完后会有 Heap dump file created 最后一个日志。

接下来用 mat 打开 dump 文件,然后用内存泄露分析的模式,通过结果看到 controller 里有大量的对象。

mat 的下载地址为 https://www. eclipse .ora/mat/,接下来看怎么确认最终的问题。 

(3) 内存-结合代码确认问题

image.png

mat 打开堆的 dump 文件之后,通过内存切入的分析就能找到 My control下面有一个历史的对象,历史对象里存在很多字符串,每个字符串的大小是两兆字节,有100多个,占用了268兆,而且可以看到具体的字符串的内容,再结合代码,

可以看到在代码里,第63行申请了一个一兆长度、两兆字节大小的内存,并且把内存放到一个全局的静态变量中进行引用,所以 jcs 无法回收,它是一个强引用,无法回收,就会导致内存泄露。通过查看堆的使用情况,以及通过 JMX 去查看堆的实际情况,或者通过 jmap 把堆 dump 出来,然后再通过 mat 工具对内存进行分析,找到占用内存的对象,再通过对象里的一些引用关系就能找到代码里创建对象的位置,这样就找到出现问题的代码,完成了内存的定位。 

2、CPU

CPU 问题一般的症状是响应应用比较慢,对应的 Java 进程 CPU 占用会比较高。

原因一般是存在大量消耗 CPU 的逻辑,或者一些循环或者是一些复杂的计算。

解决的方法,可以用 top 命令来确认进程的 CPU 占用情况,也可以通过用 jvisualvm 查看 CPU 的使用情况,就是各个线程的 CPU 的使用情况,或者通过一些第三方的工具,比如 async- profiler,对 jvm 进行新的现场剖析。

image.png

这个例子里面主机是一盒的,只有一个 CPU,它的使用率接近100%,主机的负载达到了六点多,非常高,Java 进程的 CPU 使用率可以达到99%,非常高,怎么诊断这个问题,怎么找出什么代码引起的 Java 的 CPU 占用呢?

(1)CPU-JMX 或 Jstack

image.png

JMX,看每个线程是否在执行,通过 JMX 看到线程里面的线程号1到6,它们在长期的运行,这是非常可疑的几个线程。

同时,也可以通过 Jstack 查看 JVM 里的每个线程的堆栈,通过 Jstack 的缺点就是当应用里面线程非常多的时候,Jstack 的结果非常大,有达到数万甚至十万行的结果,这个结果在十万行的日志里面去找问题会比较困难,所以期待一种更好的工具能够发现 CPU 的问题。

(2)CPU-async-profiler

可以用 async-profiler,也可以用其他的一些工具,怎么去用async-profiler 呢?第一步,去 async-profiler 的首页下载对应平台的已经编译好的代码,也可以下载源码自己编译,下载完成后,需要对它进行解压,然后找到 Java 进程,通过这一串命令/profiler.sh -e itimer -d 10 -f /share/cpu-flame-graph.svg --title "CPU profile"

3141

对 Java 进程做线程剖析,它会生成一个火焰图,通过火焰图能够准确的看到应用的热点代码。

这里对这些参数做一个说明,-e itimer 后,async-profiler 不会依赖系统内核的 perf_events,只会剖析 JVM 的内部,在有些情况下,比如在 docker 容器里面,或者一些权限的设置不允许做内核的系统剖析的时候,带上参数只做 JVM 的性能剖析基本也足够了。-d 10表示剖析持续10秒钟,会有一定间隔,跟电影一样的每隔一段时间对 JVM 做现成的快照,然后通过很多快照生成结果。最后的3141是进程号,就是 Java 的进程 id。

image.png

生成火焰图之后,用浏览器打开。可以看到六个线程霸占多长时间的 CPU,火焰图的看法是从上往下看,下面的方法是处于站底的,最上面的方法是属于站顶的,站顶的方法就是正在执行的方法,而站顶上面的最长的方法就是占用 CPU 最多的方法,可以看到这里有六个线程,里面有六个站,每个站上都是正在执行的方法,这些方法只能消耗 CPU。

再结合代码,因为从火焰图里面可以看到准确的堆栈,再通过堆栈对应到源码,可以看到正好是开了六个线程,每个线程都在执行一个很大的 FULL循环,从这里可以看到通过 JMS 可以找到可疑的线程,但是通过 async-profiler 可以生成火焰图,帮助直接定位到存在性能问题的线程以及它的堆栈,这样再通过堆栈就能通过源码找到真正有问题的代码。 

3、网络

网络里面有些常用命令需要熟练掌握。

查看当前主机 P:ip a

查看当前主机名: hostname

检查目标 P 是否可达: ping

检查目标端口是否可达: telnet

查看网卡: ifconfig

查看路由表: route n

查看从当前主机发往目标主机中间会经过哪些路由: traceroute +

查看当前主机的网卡流量: iptraf-ng

查看以 IP 为单位的网络流量排名: iftop-n

查看当前主机上监听的端口: netstat -tpnl

查看当前主机上的 TCP 连接: netstat -tpn

image.png

只有理解状态机,才能灵活的运用 TCP 的一些命令和工具,以及理解这些工具输出的结果的意义,这里对这些状态做一个说明。

CLOSED:表示当前连接已经关闭。

LISTEN:表示当前正监听中,随时准备接受连接请求。

SYN_ SENT:表示已经发送出建立 TCP 连接的数据包,等待对方回应。

SYN_ RECVD:表示接受到了建立 TCP 连接的数据包,准备给对方发送 SYN + ACK。相当于客户端发了一个建立连接的包,MySQL 也发出了一个建立连接的包。

ESTABLISHED:表示已经建立 TCP 连接。

FIN WAIT-1:表示主动关闭连接的一方已经发出了 FIN 包。

CLOSE WAIT:表示被动关闭的一方收到了 FIN 包。

FIN WAIT-2:表示主动关闭的一方收到了 FIN的 ACK 包,等待对方发出的 FIN 包。

LAST ACK :表示被动关闭的一方发出了 FIN 包,开始等待对方发出 ACK。

TIMED WAIT:表示主动关闭的一方已经发出了 ACK,此时连接已经彻底关闭,但是主动关团的一方要等待2倍 maximum segment lifetime。在此期间,任何因为网络延迟或者拥堵而未及时到达的上一个连接包抵达的时候将会被丢弃,目的是防止下一个连接收到上一个连接的包,比如当前主机跟 MySQL 之间可能会有多个连接,避免上一个连接的数据串到了下一个链接里。

(1)网络-实战

实战场景:

第一个是一段 Python 的程序,它的症状是应用僵死,就是完全阻塞,这个程序是用 Python 做例子,实际上 Java 也有类似的问题,就是 Java 里要去连接什么的时候,会发现连不上、卡住,这时通过 netstat 可以查到应用程序的进程的 TCP 连接,有一个处于 SYN SENT 状态的连接。而 SYN SENT 对应的主机和端口是根本无法连通的,所以再结合 IP 的端口去看源码,就发现原来是代码连接了一个无法连通的 IP,导致阻塞。
第二个例子就是数据库的连接数暴涨,想查到连接的来源,或者开发了一个软件,有很多连接都连到这里来了,希望知道是谁连过来的,这时在服务端执行这个网络命令,可以看到当前主机上有999个3310端口连接都来自10.0.3.15这个 IP,再去结合代码就可以找到问题。

第三个场景,就线上应用有时候没有开启 SQL 日志,SQL 不会打印到日志里面,在 DB 端可能也没有开启审计日志,怎么能看到 SQL 信息呢?

这里有一些方法:可以在应用服务器上执行 tcpdump,-i any 表示监听任意网卡,port 3310表示去 dump 3310端口。-tttt 表示在每个包前增加一个时间戳,-nn 表示不对端口和 IP 进行反向域名解析,-A 表示以应用层的方式输出日志,输出报文,它会把一些可见字符输出出来,便于排查。-s0表示一个 buffer 的控制,如果不带-s0,有可能 tcpdump 出来后,那个包的数据无法被完整地打印出来,通过命令 tcpdump-iany port 3310 -tttt -nn -A -s0可以看到网络上的铭文,但如果看到铭文的前提是 MySQL,这个客户端没有开启 SSL,一旦开启 SSL 后,所有的数据都是经过 SSL 加密的,那就无法看到铭文,这个方法对开发阶段还是很有用的。

还可以通过 tcpdump 来查看3次握手和4次挥手的网络数据。

image.png

这三个包就是3次握手,它能够去鉴定 TCP 连接,建立完 TCP 连接后,MySQL 向客户端发送提示,要求客户端输入密码,同时客户端会向 MySQL 端发送响应,告诉它我收到了这个报文,如果这时关闭了这个连接就会产生4次挥手,分别是客户端向服务器端、向 MySQL 端发送一个关闭连接的报文,然后 MySQL 会马上响应一个 ACK,同时 MySQL 也会发出关闭连接的报文,你也会给 MySQL 响应一个 ACK,这就是4次挥手,它的作用是断开连接。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
19天前
|
存储 Java 开发者
Java Map实战:用HashMap和TreeMap轻松解决复杂数据结构问题!
【10月更文挑战第17天】本文深入探讨了Java中HashMap和TreeMap两种Map类型的特性和应用场景。HashMap基于哈希表实现,支持高效的数据操作且允许键值为null;TreeMap基于红黑树实现,支持自然排序或自定义排序,确保元素有序。文章通过具体示例展示了两者的实战应用,帮助开发者根据实际需求选择合适的数据结构,提高开发效率。
50 2
|
22天前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
32 1
|
3天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
13 4
|
4天前
|
缓存 监控 Java
如何运用JAVA开发API接口?
本文详细介绍了如何使用Java开发API接口,涵盖创建、实现、测试和部署接口的关键步骤。同时,讨论了接口的安全性设计和设计原则,帮助开发者构建高效、安全、易于维护的API接口。
21 4
|
15天前
|
开发框架 JavaScript 前端开发
HarmonyOS UI开发:掌握ArkUI(包括Java UI和JS UI)进行界面开发
【10月更文挑战第22天】随着科技发展,操作系统呈现多元化趋势。华为推出的HarmonyOS以其全场景、多设备特性备受关注。本文介绍HarmonyOS的UI开发框架ArkUI,探讨Java UI和JS UI两种开发方式。Java UI适合复杂界面开发,性能较高;JS UI适合快速开发简单界面,跨平台性好。掌握ArkUI可高效打造符合用户需求的界面。
62 8
|
10天前
|
SQL Java 程序员
倍增 Java 程序员的开发效率
应用计算困境:Java 作为主流开发语言,在数据处理方面存在复杂度高的问题,而 SQL 虽然简洁但受限于数据库架构。SPL(Structured Process Language)是一种纯 Java 开发的数据处理语言,结合了 Java 的架构灵活性和 SQL 的简洁性。SPL 提供简洁的语法、完善的计算能力、高效的 IDE、大数据支持、与 Java 应用无缝集成以及开放性和热切换特性,能够大幅提升开发效率和性能。
|
10天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
26 2
|
10天前
|
监控 Java 数据库连接
在Java开发中,数据库连接管理是关键问题之一
在Java开发中,数据库连接管理是关键问题之一。本文介绍了连接池技术如何通过预创建和管理数据库连接,提高数据库操作的性能和稳定性,减少资源消耗,并简化连接管理。通过示例代码展示了HikariCP连接池的实际应用。
14 1
|
16天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
19天前
|
Java 大数据 API
别死脑筋,赶紧学起来!Java之Steam() API 常用方法使用,让开发简单起来!
分享Java Stream API的常用方法,让开发更简单。涵盖filter、map、sorted等操作,提高代码效率与可读性。关注公众号,了解更多技术内容。

推荐镜像

更多
下一篇
无影云桌面