SQL基础—事务Transaction

本文介绍了SQL中的事务概念,包括事务的四大特性(ACID)、并发访问问题及隔离级别。通过实例解释了事务在确保数据一致性、避免并发问题中的重要性。还探讨了SQL中隐式和显式事务的使用,以及JDBC和DBUtils中如何进行事务操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么是事务?为什么要用事务?


什么是事务?

一个事务是由一条或者多条sql语句构成,这一条或者多条sql语句要么全部执行成功,要么全部执行失败!

那为什么要使用事务呢???

举例:

银行转账!张三转10000块到李四的账户,这其实需要两条SQL语句:

  • 给张三的账户减去10000元;
  • 给李四的账户加上10000元。

如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么李四的账户没有加上10000元,而张三却减去了10000元。这肯定是不行的!

事务中的多个操作,要么完全成功,要么完全失败!不可能存在成功一半的情况!也就是说给张三的账户减去10000元如果成功了,那么给李四的账户加上10000元的操作也必须是成功的;否则给张三减去10000元,以及给李四加上10000元都是失败的!

2.事务的特性


2.1 事务的四大特性(ACID)

1.原子性(Atomicity):

  • 事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。

2.一致性(Consistency):

  • 事务执行前后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。

3.隔离性(Isolation):

  • 隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰

4.持久性(Durability):

  • 一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中。即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

2.2 数据库的并发访问问题

如果不考虑隔离性,事务存在3中并发访问问题:

1)脏读:一个事务读到了另一个事务未提交的数据

  • 未提交的数据很有可能会被回滚

2)不可重复读:一个事务读到了另一个事务已经提交(update)的数据。引发这个事务,在事务中的多次查询结果不一致。

  • 前后读取到的对应记录,其值不同(行级)

3)虚读 /幻读:一个事务读到了另一个事务已经提交(insert)的数据。导致这个事务,在事务中多次查询的结果不一致。

  • 前后查询到的记录数不同(表级)

2.3 数据库的隔离级别:解决问题

数据库规范规定了4种隔离级别,分别用于描述两个事务并发的所有情况:

1.read uncommitted 读未提交:一个事务读到另一个事务没有提交的数据。

  • a)存在:3个问题(脏读、不可重复读、虚读)
  • b)解决:0个问题

2.read committed 读已提交:一个事务读到另一个事务已经提交的数据。

  • a)存在:2个问题(不可重复读、虚读)。
  • b)解决:1个问题(脏读)

3.repeatable read可重复读:在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。

  • a)存在:1个问题(虚读)。
  • b)解决:2个问题(脏读、不可重复读)

4.serializable 串行化:同时只能执行一个事务,相当于事务中的单线程。

  • a)存在:0个问题。
  • b)解决:3个问题(脏读、不可重复读、虚读)

安全和性能对比:

  • 1)安全性:
    • serializable(8) > repeatable read(4) > read committed(2) > read uncommitted(1)
  • 2)性能 :
    • serializable < repeatable read < read committed < read uncommitted
  • 3)级别越高,越安全,效率越低。

常见数据库的默认隔离级别:

  • MySql:repeatable read 可重复读
  • Oracle:read committed 读已提交

3.SQL中事务的使用


事务可以分为:

  • 1)隐式事务:没有明显的开始和结束的标记——如:insert、update、delete、select本身就是一个事务
  • 2)显式事务:具有明显的开始和结束的标记

3.1 隐式事务

将Autocommit——"自动提交"设置为ON:

SHOW variables like '%auto%';  --> 查看是否设置自动提交
  • 在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。
  • 如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。

3.2 显式事务

在执行SQL语句之前,先执行start transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务:

  • commit:表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。
  • rollback:表示回滚,即回滚到事务的起点,之前做的所有操作都被撤消了!

步骤:

1>开启事务:撤销事务自动提交的功能,并开启事务

SET autocommit = 0; /*自动提交设置为OFF—— 0:OFF  1:ON */
START TRANSACTION;  /*开启事务:可选*/

2>编写事务的组成语句:1 或 多条SQL语句

insert
update
delete
select

3>结束事务:提交/回滚

ROLLBACK;
/*或*/
COMMIT;

注意:

1)只有insert、update、delete、select 语句才支持事务

2)delete 和 truncate 是否支持事务?

  • delete支持事务
  • truncate 不支持事务
SET autocommit = 0;
DELETE FROM account;
ROLLBACK;

/*以下事务会运行出错*/
SET autocommit = 0;
TRUNCATE TABLE account;
ROLLBACK;

4.Jdbc事务操作

Connection 对象的方法名描述
conn.setAutoCommit(false)开启事务
conn.commit()提交事务
conn.rollback()回滚事务

代码演示

//事务模板代码
public void demo01() throws SQLException{
	// 获得连接
	Connection conn = null;
	
	try {
		//#1 开始事务:设置自动提交为false
		conn.setAutoCommit(false);
		
		//2 数据库操纵.... 加钱 ,减钱
		
		//#3.1 运行成功,则提交事务
		conn.commit();
	} catch (Exception e) {
		//#3.2 出现异常,则回滚事务
		conn.rollback();
	} finally{
		// 释放资源
		conn.close();
	}
}

5. DBUtils事务操作

Connection对象的方法名描述
conn.setAutoCommit(false)开启事务
new QueryRunner()创建核心类,不设置数据源(手动管理连接)
query(conn , sql , handler, params ) 或
update(conn, sql , params)
手动传递连接, 执行SQL语句CRUD
DbUtils.commitAndCloseQuietly(conn)提交并关闭连接,不抛异常
DbUtils.rollbackAndCloseQuietly(conn)回滚并关闭连接,不抛异常

代码演示

//事务模板代码
public void demo02() throws SQLException{
	// 获得连接
	Connection conn = null;
	
	try {
		//#1 开始事务
		conn.setAutoCommit(false);
		
		//.... 加钱 ,减钱
		
		//#2 提交事务
		DbUtils.ommitAndCloseQuietly(conn); 
	} catch (Exception e) {
		//#3 回滚事务
		DbUtils.rollbackAndCloseQuietly(conn);
        e.printStackTrace();
	} 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值