JDBC 处理事务的隔离级别

各种并发的问题

  • 脏读:对于两个事务 T1,T2,T1 读取了已经被 T2 更新但还没有被提交的字段之后,若 T2 回滚,T1 读取的内容就是临时且无效的。
  • 不可重复读:对于两个事物 T1 T2 ,T1 读取了一个字段,然后 T2 更新了该字段之后,T1 再次读取同一个字段,值就不同了。
  • 幻读:对于两个事物 T1 T2,T1 从一个表中读取了一个字段,然后 T2 在该表中插入了一些新的行之后,如果 T1 再次读取同一个表,就会多出几行。

事务的隔离级别在这里插入图片描述在这里插入图片描述

设置隔离级别的两种方式

  • 在Java程序中
    查看:System.out.println(connection.getTransactionIsolation());
    设置:connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
  • 在 MySQL中
    查看:SELECT @@tx_isolation
    设置当前MySQL连接的隔离级别 set transaction isolation level read committed;
    设置数据库系统的全局的隔离级别 set global transaction isolation lenel rad committed;

Java测试设置隔离级别未提交

//返回某条记录的某一个字段的值或一个统计的值
 public <E> E getForValue(String sql,Object ...args){
	  Connection connection = null;
	  PreparedStatement preparedStatement = null;
	  ResultSet resultSet = null;
	  try {
	   	connection = JDBCTools.getConnection();
	   	
	   	//设置隔离级别--读未提交/读已提交
	   	connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
		//connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
	   
		 preparedStatement = connection.prepareStatement(sql);
		 for(int i = 0;i < args.length;i++){
		   	preparedStatement.setObject(i+1, args[i]);
		 }
		 resultSet = preparedStatement.executeQuery();
		 if(resultSet.next()){
		    	return (E) resultSet.getObject(1);
		 }
	  } catch (Exception e) {
	   	e.printStackTrace();
	  } finally{
	   	JDBCTools.release(resultSet, preparedStatement, connection);
	  }
		  return null;
	 }
/**
  * 测试事务的隔离级别在 JDBC 程序中可以通过 Connection 的 setTransactionIsolation
  * 来设置事务的隔离级别
  */
 @Test
 public void testTransactionIsolationUpdate(){
	  Connection connection = null;
	  try {
		   connection = JDBCTools.getConnection();
		   connection.setAutoCommit(false);
		   String sql = "UPDATE users SET balance = balance-500 WHERE id = ?";
		   update(connection, sql,1);
		   connection.commit();//该行进行断点调试
	  } catch (Exception e) { 
	   	e.printStackTrace();
	  }finally{
	   	JDBCTools.release(null, null, connection);
	  }
}
@Test
 public void testTransactionIsolationRead(){
	  String sql = "SELECT balance FROM users WHERE id = 1";
	  Integer balance = getForValue(sql);
	  System.out.println(balance);
}

数据库:
在这里插入图片描述
设置隔离级别读未提交时:(数据库 balance == 1000 发生脏读、幻读、不可重复读)
在这里插入图片描述
设置隔离级别读已提交时:(数据库 balance == 1000 发生不可重复读和幻读,可避免脏读)
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值