MySQL+JDBC 核心实战笔记:事务隔离级别、索引优化与常见异常解决方案
本文适合 Java+MySQL 开发新手,系统梳理 JDBC 操作 MySQL 的核心知识点:事务隔离级别配置、索引优化实战、常见异常排查方案,附可直接运行的代码示例,学习 / 面试都能用!
一、前置知识:JDBC 操作 MySQL 基础
1.1 依赖引入(Maven)
使用 MySQL 8.0 + 驱动,注意驱动类和 URL 语法变化:
xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
1.2 JDBC 连接 MySQL 固定模板
java
运行
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JDBCUtil {
// MySQL 8.0+ 连接参数
private static final String URL = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
private static final String USER = "root";
private static final String PASSWORD = "123456";
// 获取数据库连接
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("数据库连接成功!");
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
// 关闭连接
public static void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
二、MySQL 事务隔离级别(JDBC 配置 + 原理)
2.1 事务四大特性(ACID)
-
原子性:事务要么全部执行,要么全部回滚
-
一致性:执行前后数据完整性不变
-
隔离性:多个事务互不干扰
-
持久性:事务提交后数据永久生效
2.2 事务并发三大问题
-
脏读:一个事务读取到另一个未提交的事务数据
-
不可重复读:同一事务内,两次查询结果不一致(其他事务修改了数据)
-
幻读:同一事务内,两次查询行数不一致(其他事务插入 / 删除数据)
2.3 MySQL 四大隔离级别(从低到高)
表格
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| 读未提交(READ UNCOMMITTED) | ✅ | ✅ | ✅ | 最高 |
| 读已提交(READ COMMITTED) | ❌ | ✅ | ✅ | 高 |
| 可重复读(REPEATABLE READ) | ❌ | ❌ | ❌ | 中 |
| 串行化(SERIALIZABLE) | ❌ | ❌ | ❌ | 最低 |
✨ 默认级别:MySQL 默认使用可重复读(RR),Oracle 默认读已提交(RC)
2.4 JDBC 设置事务隔离级别
JDBC 通过Connection对象设置隔离级别,核心代码:
java
运行
public class TransactionTest {
public static void main(String[] args) {
Connection conn = JDBCUtil.getConnection();
try {
// 1. 关闭自动提交(开启事务)
conn.setAutoCommit(false);
// 2. 设置事务隔离级别:4种常量可选
// Connection.TRANSACTION_READ_UNCOMMITTED 读未提交
// Connection.TRANSACTION_READ_COMMITTED 读已提交
// Connection.TRANSACTION_REPEATABLE_READ 可重复读(默认)
// Connection.TRANSACTION_SERIALIZABLE 串行化
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
// 3. 执行业务SQL(省略)
System.out.println("事务执行中...");
// 4. 提交事务
conn.commit();
System.out.println("事务提交成功!");
} catch (SQLException e) {
e.printStackTrace();
try {
// 5. 异常回滚事务
conn.rollback();
System.out.println("事务已回滚!");
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
JDBCUtil.close(conn);
}
}
}
2.5 查看 / 修改 MySQL 全局隔离级别
sql
-- 查看当前隔离级别
SELECT @@transaction_isolation;
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
三、MySQL 索引优化实战(高频面试 + 工作必备)
3.1 索引是什么?
索引是优化查询速度的数据结构(默认 B + 树),相当于书的目录,能大幅减少查询 IO。
3.2 索引分类
-
主键索引:
PRIMARY KEY,唯一且非空,一张表只能有一个 -
唯一索引:
UNIQUE,列值唯一,允许 NULL -
普通索引:
INDEX,仅加速查询 -
联合索引:多个字段组合索引,遵循最左前缀原则
-
全文索引:
FULLTEXT,用于文本搜索
3.3 索引创建 / 删除语法
sql
-- 1. 创建普通索引
CREATE INDEX idx_user_name ON user(name);
-- 2. 创建唯一索引
CREATE UNIQUE INDEX idx_user_phone ON user(phone);
-- 3. 创建联合索引(最常用!)
CREATE INDEX idx_user_name_age ON user(name, age);
-- 4. 删除索引
DROP INDEX idx_user_name ON user;
3.4 索引优化核心规则(必背)
-
最左前缀原则
:联合索引必须从左到右使用,否则索引失效
sql -- 有效:使用联合索引 idx(name,age) SELECT * FROM user WHERE name='张三' AND age=20; -- 失效:跳过name直接查age SELECT * FROM user WHERE age=20; -
避免索引列运算 / 函数
:索引列上使用函数、计算会导致索引失效
sql -- 失效 SELECT * FROM user WHERE age+1=20; -- 有效 SELECT * FROM user WHERE age=19; -
模糊查询以 % 开头失效
sql -- 失效 SELECT * FROM user WHERE name LIKE '%张三'; -- 有效 SELECT * FROM user WHERE name LIKE '张三%'; -
** 避免使用 SELECT ***:只查询需要的字段,减少回表
-
order by/group by 遵循索引规则:排序字段最好建立索引
3.5 执行计划:EXPLAIN 分析索引
使用EXPLAIN查看 SQL 是否使用索引:
sql
EXPLAIN SELECT * FROM user WHERE name='张三';
关键字段:
-
type:最优const>ref>range>ALL(全表扫描) -
key:显示使用的索引,NULL表示未使用索引 -
rows:扫描行数,越小越好
四、JDBC+MySQL 常见异常及解决方案
异常 1:Communications link failure(连接失败)
报错信息
Could not create connection to database server
原因
-
MySQL 服务未启动
-
连接 URL / 账号密码错误
-
MySQL 8.0 + 驱动类错误
解决方案
:
-
启动 MySQL 服务
-
检查 URL:
jdbc:mysql://localhost:3306/库名 -
驱动类:
com.mysql.cj.jdbc.Driver(8.0 + 必须加 cj)
异常 2:java.sql.SQLException: 没有自动提交,不能执行更新
原因
autoCommit
commit/rollback
解决方案
-
增删改操作必须手动调用
conn.commit() -
异常时必须调用
conn.rollback()
异常 3:Lock wait timeout exceeded; try restarting transaction(锁等待超时)
原因
解决方案
-
优化事务,缩短事务执行时间
-
检查未提交事务:
SELECT * FROM information_schema.innodb_trx; -
kill 阻塞事务
异常 4:Duplicate entry 'xxx' for key 'PRIMARY'(主键冲突)
原因
解决方案
-
主键设置自增
AUTO_INCREMENT -
插入数据时不指定主键字段
异常 5:JDBC 中文乱码
原因
解决方案
plaintext
jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8
异常 6:Too many connections(连接数过多)
原因
解决方案
-
必须在
finally中关闭Connection -
使用连接池(Druid/HikariCP)管理连接
五、总结
-
事务隔离级别:MySQL 默认可重复读,解决脏读、不可重复读、幻读,JDBC 通过
Connection配置 -
索引优化:核心是避免索引失效,联合索引遵循最左前缀,用 EXPLAIN 分析 SQL
-
异常处理:重点关注连接失败、事务未提交、中文乱码、连接泄漏问题
📌 补充建议
-
生产环境必须使用连接池(Druid 推荐),不要手动创建连接
-
事务不要嵌套,避免长事务
-
高频查询字段必须建索引,低频率字段不建索引(降低写入性能)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)