温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中事务的特性有哪几种

发布时间:2022-01-12 09:14:00 来源:亿速云 阅读:187 作者:iii 栏目:大数据

这篇“java中事务的特性有哪几种”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“java中事务的特性有哪几种”文章吧。

Java中事务的特性有四种,原子性、一致性、隔离性、持久性

原子性:如果执行一条sql,底层是默认执行事务的,叫做隐形事务,当执行多条sql语句的时候,多条sql语句不可以进行分割,必须全部一次性执行完成,就是要么全部完成,要么失败;

一致性:事务完成后,数据状态保持一致性,能量守恒定律,哈哈哈;

隔离性:多个事务并发访问数据库,事务对数据的修改,需要与其他事务进行隔离;

持久性:数据修改完成,数据持久化存储;

使用JDBC,需要先关闭主动提交事务,然后执行多条SQL语句,然后提交,如果报错进行回滚事务,在最后启动自动提交,因为执行1条sql语句的时候,也会开启事务,叫做隐形事务,默认进行提交,如果关闭了不启动,以后执行一条SQL也需要显示显示事务了;

Connection conn = openConnection();
try {
    // 关闭自动提交:
    conn.setAutoCommit(false);// 执行多条SQL语句:insert(); update(); delete();// 提交事务:
    conn.commit();} catch (SQLException e) {
    // 回滚事务:
    conn.rollback();} finally {
    conn.setAutoCommit(true);conn.close();
}

Mysql隔离级别分为4种:Read Uncommitted(读取未提交的)、Read Committed(读取提交的)、Repeatable Red(可重复读)、Serializaable(串行化)

Isolation Level脏读(Dirty Read)不可重复读(Non Repeatable Read)幻读(Phantom Read)
Read UncommittedYesYesYes
Read Committed-YesYes
Repeatable Read--Yes
Serializable---

Read Uncommitted是隔离级别最低的一种事务级别。在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据,这就是脏读(Dirty Read)。

mysql> select * from students;+----+-------+| id | name  |
+----+-------+|  1 | Alice |
+----+-------+1 row in set (0.00 sec)

然后,分别开启两个MySQL客户端连接,按顺序依次执行事务A和事务B:

当事务A执行完第3步时,它更新了id=1的记录,但并未提交,而事务B在第4步读取到的数据就是未提交的数据。

随后,事务A在第5步进行了回滚,事务B再次读取id=1的记录,发现和上一次读取到的数据不一致,这就是脏读。

可见,在Read Uncommitted隔离级别下,一个事务可能读取到另一个事务更新但未提交的数据,这个数据有可能是脏数据。

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
2BEGIN;BEGIN;
3UPDATE students SET name = 'Bob' WHERE id = 1; 
4 SELECT * FROM students WHERE id = 1;
5ROLLBACK; 
6 SELECT * FROM students WHERE id = 1;
7 COMMIT;

在Read Committed隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。

不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。

我们仍然先准备好students表的数据:

mysql> select * from students;+----+-------+| id | name  |
+----+-------+|  1 | Alice |
+----+-------+1 row in set (0.00 sec)

然后,分别开启两个MySQL客户端连接,按顺序依次执行事务A和事务B:

当事务B第一次执行第3步的查询时,得到的结果是Alice,随后,由于事务A在第4步更新了这条记录并提交,所以,事务B在第6步再次执行同样的查询时,得到的结果就变成了Bob,因此,在Read Committed隔离级别下,事务不可重复读同一条记录,因为很可能读到的结果不一致。

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL READ COMMITTED;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
2BEGIN;BEGIN;
3 SELECT * FROM students WHERE id = 1;
4UPDATE students SET name = 'Bob' WHERE id = 1; 
5COMMIT; 
6 SELECT * FROM students WHERE id = 1;
7 COMMIT;

在Repeatable Read隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。

幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。

我们仍然先准备好students表的数据:

mysql> select * from students;+----+-------+| id | name  |
+----+-------+|  1 | Alice |
+----+-------+1 row in set (0.00 sec)

然后,分别开启两个MySQL客户端连接,按顺序依次执行事务A和事务B:

事务B在第3步第一次读取id=99的记录时,读到的记录为空,说明不存在id=99的记录。随后,事务A在第4步插入了一条id=99的记录并提交。事务B在第6步再次读取id=99的记录时,读到的记录仍然为空,但是,事务B在第7步试图更新这条不存在的记录时,竟然成功了,并且,事务B在第8步再次读取id=99的记录时,记录出现了。

可见,幻读就是没有读到的记录,以为不存在,但其实是可以更新成功的,并且,更新成功后,再次读取,就出现了。

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2BEGIN;BEGIN;
3 SELECT * FROM students WHERE id = 99;
4INSERT INTO students (id, name) VALUES (99, 'Bob'); 
5COMMIT; 
6 SELECT * FROM students WHERE id = 99;
7 UPDATE students SET name = 'Alice' WHERE id = 99;
8 SELECT * FROM students WHERE id = 99;
9 COMMIT;

Serializable是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。

虽然Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用Serializable隔离级别。

默认隔离级别

如果没有指定隔离级别,数据库就会使用默认的隔离级别。在MySQL中,如果使用InnoDB,默认的隔离级别是Repeatable Read。

启动事务

在启动类上添加注解 @EnableTransactionManagement ,

在执行事务的方法上面使用 @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)设置隔离界别与事务传播。默认就是REQUIRED;

事务传播

Spring的声明式事务为事务传播定义了几个级别,默认传播级别就是REQUIRED,它的意思是,如果当前没有事务,就创建一个新事务,如果当前有事务,就加入到当前事务中执行。

SUPPORTS:表示如果有事务,就加入到当前事务,如果没有,那也不开启事务执行。这种传播级别可用于查询方法,因为SELECT语句既可以在事务内执行,也可以不需要事务;

MANDATORY:表示必须要存在当前事务并加入执行,否则将抛出异常。这种传播级别可用于核心更新逻辑,比如用户余额变更,它总是被其他事务方法调用,不能直接由非事务方法调用;

REQUIRES_NEW:表示不管当前有没有事务,都必须开启一个新的事务执行。如果当前已经有事务,那么当前事务会挂起,等新事务完成后,再恢复执行;

NOT_SUPPORTED:表示不支持事务,如果当前有事务,那么当前事务会挂起,等这个方法执行完成后,再恢复执行;

NEVER:和NOT_SUPPORTED相比,它不但不支持事务,而且在监测到当前有事务时,会抛出异常拒绝执行;

NESTED:表示如果当前有事务,则开启一个嵌套级别事务,如果当前没有事务,则开启一个新事务。

以上就是关于“java中事务的特性有哪几种”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI