刚刚写完事务控制原理的理解,趁热打铁,顺便也把隔离级别说说。主要就是给演示一下jdbc的脏读(其他的隔离级别就不实现了,顺着这个思路自行实验吧,主要通过这个实验给你更加直观的体验)。
隔离级别的概念也算数据库操作中比较有名的了吧,以前也常听人说起,但是一直未曾见其真身,一提起这个名词总感觉晕晕乎乎的,似乎知道,但又不知道,今天成有机会,来自行实现一把,看看他的真身,也加深自己的理解。
准备的原材料
一张简单的表,就一条数据,但是够了。
隔离节别表,这里偷个懒,截上图放这把。
至于这些级别的更详细的解释,这里就不介绍了,推荐大家看这篇博文,讲的很好。
mysql tx_isolation
这些隔离级别在MySQL数据库中的查看方式如下:
select @@transaction_isolation; //我用的是8版本的数据库
select @@tx_isolation; //低版本的
设置MySQL的隔离级别
set transaction_isolation = ‘read-uncommitted’; //支持脏读
select @@transaction_isolation;
更改设置之后的隔离级别
代码如下
在update
操作commit
之前读取数据。
public static void main(String[] args) throws ClassNotFoundException, SQLException, InterruptedException {
Connection conn = null;
Statement statement = null;
//1、注册驱动
//本地安装的数据库版本要和驱动版本对应,否则报错无法创建连接
Class.forName("com.mysql.cj.jdbc.Driver");
//2、获取连接
conn = DriverManager.getConnection(url, dbName, dbPass);
conn.setAutoCommit(false); //关闭自动提交
//3、获取一个statement
statement = conn.createStatement();
//4、执行更新的sql语句
String sqlUpdate = "update account set money=0 where name='张三'";
statement.execute(sqlUpdate);
//5、执行查询sql语句,查询未提交的数据
//脏读产生点
String sqlQuery = "select * from account where name='张三'";
ResultSet resultSet = statement.executeQuery(sqlQuery);
while (resultSet.next()){
System.out.println(resultSet.getInt("money"));
}
conn.commit();
//5、关闭statement和connection
if (statement!=null){
statement.close();
}
if (conn!=null){
conn.close();
}
结果是什么你们想一下,0?
1000,WTK?
我明明在MySQL中修改成了read uncommitted(未提交读)
呀。
但是不应该在MySQL中设置,而应该在jdbc代码中设置(其实我很不理解,我的底层都支持了,你一个调用我的,竟然敢违背我。是在不解这是怎么回事,还望路过的大佬不吝赐教)。
下面我们的看一下connection的一些我们平时用的比较少的功能。
//获得jdbc的connection的隔离级别,我是第一次用,原谅我是个菜鸟
int isolation = conn.getTransactionIsolation();
System.out.println("isolation = " + isolation);
不应该上面说的那些吗,怎么出来一个整数呢。原来这群人又在完幺蛾子
可以看到我们现在的级别根本就不支持脏读,所以还需要设置一下隔离级别
//2、获取连接
conn = DriverManager.getConnection(url, dbName, dbPass);
conn.setAutoCommit(false); //关闭自动提交
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
这回就对了嘛。
所以说在spring的配置中,我们才可以在代码中配置事务的隔离级别,而不是去修改物理的MySQL的隔离级别。