在上海乐字节学习Java的第十八天

本文详细介绍了Java中的事务概念及其重要性,包括数据库事务的ACID特性、MySQL和JDBC下的事务管理方式,以及事务隔离级别的设置与示例。通过对银行转账案例的分析,阐述了事务如何保证数据完整性,防止脏读、不可重复读和虚读等问题。此外,还讨论了事务隔离级别设置对性能和安全的影响,并提到了解决丢失更新的方法,如悲观锁和乐观锁。最后,探讨了连接池的概念、作用及实现原理,推荐了DBCP和C3P0等开源连接池,并展示了如何在Tomcat中配置数据源。
摘要由CSDN通过智能技术生成

事务
事务的概念
事务就是一个事情,组成这个事情可能有多个单元,要求这些单元,要么全都成功,要么全都不成功。
在开发中,有事务的存在,可以保证数据完整性。

例如:A——B转帐,对应于如下两条sql语句

update account set money=money-100 where name=‘a’;
update account set money=money+100 where name=‘b’;
数据库默认事务是自动提交的,也就是发一条sql它就执行一条。如果想多条sql放在一个事务中执行,则需要使用如下语句。
Start transaction

commit
MySQL下操作事物
方式1:

start transaction 开启事务
rollback 事务回滚
commit 事务提交
方式2:

show variables like ‘%commit%’; 可以查看当前autocommit值
在mysql数据库中它的默认值是”on”代表自动事务.
自动事务的意义就是:执行任意一条sql语句都会自动提交事务.
测试:将autocommit的值设置为off

1.set autocommit=off 关闭自动事务。

2.必须手动commit才可以将事务提交。

注意:mysql默认autocommit=on oracle默认的autocommit=off;

JDBC下操作事物
当Jdbc程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会自动向数据库提交在它上面发送的SQL语句。若想关闭这种默认提交方式,让多条SQL在一个事务中执行,可使用下列语句:
java.sql.Connection接口中有几个方法是用于可以操作事务
1.setAutocommit(boolean flag);
如果flag=false;它就相当于start transaction;
2.rollBack()
事务回滚。
3.commit()
事务提交
银行转帐案例
在JDBC代码中使如下转帐操作在同一事务中执行。
update from account set money=money-100 where name=‘a’;
update from account set money=money+100 where name=‘b’;
设置事务回滚点
Savepoint sp = conn.setSavepoint();
Conn.rollback(sp);
Conn.commit(); //回滚后必须要提交
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);

insert into account values(null,‘aaa’,1000);
insert into account values(null,‘bbb’,1000);
insert into account values(null,‘ccc’,1000);

事务特性(重点) ACID
原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency)
事务前后数据的完整性必须保持一致。
隔离性(Isolation)
事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

事务的隔离级别
多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。
如果不考虑隔离性,可能会引发的问题
1.脏读 一个事务读取到另一个事务的未提交数据。

这是非常危险的,假设A向B转帐100元,对应sql语句如下所示
1.update account set money=money+100 while name=‘b’;
2.update account set money=money-100 while name=‘a’;
当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。
2.不可重复读

在一个事务内读取表中的某一行数据,多次读取结果不同。(update)
例如银行想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户存了100元并提交了,银行接着又进行了一次查询,此时A帐户为300元了。银行两次查询不一致,可能就会很困惑,不知道哪次查询是准的。
和脏读的区别是,脏读是读取前一事务未提交的脏数据,不可重复读是重新读取了前一事务已提交的数据。
很多人认为这种情况就对了,无须困惑,当然是后面的为准。我们可以考虑这样一种情况,比如银行程序需要将查询结果分别输出到电脑屏幕和写到文件中,结果在一个事务中针对输出的目的地,进行的两次查询不一致,导致文件和屏幕中的结果不一致,银行工作人员就不知道以哪个为准了。
3.虚读(幻读)

是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。(insert)
如丙存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后丙提交了,这时银行再统计发现帐户为600元了,造成虚读同样会使银行不知所措,到底以哪个为准。
4.丢失更新

两个或多个事务更新同一行,但这些事务彼此之间都不知道其它事务进行的修改,因此第二个更改覆盖了第一个修改

事务隔离性的设置语句
数据库共定义了四种隔离级别:

Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。不可以避免虚读
Read committed:可避免脏读情况发生(读已提交)
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)
安全性:serializable > repeatable read > read committed > read uncommitted

性能 :serializable < repeatable read < read committed < read uncommitted

结论: 实际开发中,通常不会选择 serializable 和 read uncommitted ,

怎样设置事务的隔离级别?

1.mysql中设置

1.查看事务隔离级别
select @@tx_isolation 查询当前事务隔离级别
mysql中默认的事务隔离级别是 Repeatable read.
oracle 中默认的事务隔离级别是 Read committed
2.mysql中怎样设置事务隔离级别
set session transaction isolation level 设置事务隔离级别
2.jdbc中设置

在jdbc中设置事务隔离级别
使用java.sql.Connection接口中提供的方法
void setTransactionIsolation(int level) throws SQLException
参数level可以取以下值:
TRANSACTION_READ_UNCOMMITTED,指示可以发生脏读、不可重复读、虚读。
TRANSACTION_READ_COMMITTED:指示不可以发生脏读,但是不可重复读、虚读可以发生。
TRANSACTION_REPEATABLE_READ:指示不可以发生脏读、不可重复读,但是虚读可以发生。
TRANSACTION_SERIALIZABLE:指示不可以发生脏读、不可重复读和虚读的常量。
TRANSACTION_NONE,一般不使用&#x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值