事务操作
事务概述
1.事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败.
2.事务作用:保证在一个事务中多次SQL操作要么全都成功,要么全都失
sql语句 | 描述 |
---|---|
start transaction | 开启事务 |
commit | 提交事务 |
rollback | 回滚事务 |
Connection 对象的方法名 描述
QL中可以有两种方式进行事务的管理:
自动提交:MySql默认自动提交。及执行一条sql语句提交一次事务。
手动提交:先开启,再提交
方式1:手动提交
start transaction;
update account set money=money-1000 where name='jack';
update account set money=money+1000 where name='rose';
commit; #或者 rollback
方式2:自动提交,通过修改mysql全局变量“autocommit”进行控制
show variables like '%commit%';
* 设置自动提交的参数为OFF:
set autocommit = 0; -- 0:OFF 1:ON
jdbc事务操作
conn.setAutoCommit(false) 开启事务
conn.commit() 提交事务
conn.rollback() 回滚事务
DBUtils事务操作
Connection对象的方法名 | 描述 |
---|---|
conn.setAutoCommit(false) | 开启事务 |
new QueryRunner() | 创建核心类,不设置数据源(手动管理连接) |
query(conn , sql , handler, params ) 或 update(conn, sql , params) | 手动传递连接, 执行SQL语句CRUD |
DbUtils.commitAndCloseQuietly(conn) | 提交并关闭连接,不抛异常 |
DbUtils.rollbackAndCloseQuietly(conn) | 回滚并关闭连接,不抛异常 |
JDBC事务分层(dao、service、web)
开发中,常使用分层思想
不同的层次结构分配不同的解决过程,各个层次间组成严密的封闭系统
不同层级结构彼此平等
分层的目的是:
- 解耦
- 可维护性
- 可扩展性
- 可重用性
不同层次,使用不同的包表示
ThreadLocal
在JDK中给我们提供了一个工具类:ThreadLocal,此类可以在一个线程中共享数据。 java.lang.ThreadLocal 该类提供了线程局部 (thread-local) 变量,用于在当前线程中共享数据。
ThreadLocal工具 类底层就是相当于一个Map,key存放的当前线程,value存放需要共享的数据。
ThreadLocal的底层原理:使用一个Map集合,对Map进行了封装
Map<当前线程Thread,Object> map = new HashMap<当前线程Thread,Object>();
当前线程Thread:static Thread currentThread()
在使用方法的时候,省略了Map集合的key,只使用了Map集合的vlaue,key默认就是用的当前正在执行的线程
ThreadLocal构造方法:
ThreadLocal() 创建一个线程本地变量。
ThreadLocal的成员方法:
void set(T value) 往ThreadLocal中添加数据
此方法相当于Map集合的put方法
put(Thread.currentThread(),Value);
T get() 通过当前线程,获取当前线程保存的值
此方法相当于Map集合的get方法
value = get(Thread.currentThread());
void remove() 通过当前线程,移除ThreadLocal中保存的健值
此方法相当于Map集合的remove方法
remove(Thread.currentThread())
线程局部(自己) (thread-local) 变量。
哪个线程往ThreadLocal中存储的数据,只有哪个线程能使用,其他线程不能使用
结论:向ThreadLocal对象中添加的数据只能在当前线程下使用。
事务总结
1 事务特性:ACID
原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency)事务前后数据的完整性必须保持一致。
隔离性(Isolation)事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务 所干扰,多个并发事务之间数据要相互隔离。
持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使 数据库发生故障也不应该对其有任何影响。
2 并发访问问题
如果不考虑隔离性,事务存在3中并发访问问题。
- 脏读:一个事务读到了另一个事务未提交的数据.(update后,commit/rollback前)
- 不可重复读:一个事务读到了另一个事务已经提交(update)的数据。 引发另一个事务,在事务中的多次查询结 果不一致。 (update后,commit后)
- 虚读 /幻读:一个事务读到了另一个事务已经提交(insert)的数据。(很少发生) 记录的增加和减少会导致幻读的产生。导致另一个事务,在事务中多次查询的结果 不一致。
3 隔离级别:解决问题
数据库规范规定了4种隔离级别,分别用于描述两个事务并发的所有情况。
-
read uncommitted 读未提交,一个事务读到另一个事务没有提交的数据。
a)存在:3个问题(脏读、不可重复读、虚读)。
b)解决:0个问题 -
read committed 读已提交,一个事务读到另一个事务已经提交的数据。
a)存在:2个问题(不可重复读、虚读)。
b)解决:1个问题(脏读) -
repeatable read:可重复读,在一个事务中读到的数据始终保持一致,无论另一个事务是否提交。
a)存在:1个问题(虚读)。
b)解决:2个问题(脏读、不可重复读) -
serializable 串行化,同时只能执行一个事务,相当于事务中的单线程。
a)存在:0个问题。
b)解决:3个问题(脏读、不可重复读、虚读)
安全和性能对比
安全性: serializable > repeatable read > read committed > read uncommitted
性能 : serializable < repeatable read < read committed < read uncommitted
常见数据库的默认隔离级别:
MySql: repeatable read
Oracle: read committed
在Connection接口中有设置事务隔离级别的方法(了解)
void setTransactionIsolation(int level) 试图将此 Connection 对象的事务隔离级别更改为给定的级别。
参数:
int level:
serializable(8) > repeatable read(4) > read committed(2) > read uncommitted(1)
Connection接口中定义的常量(建议)
int TRANSACTION_NONE = 0;
int TRANSACTION_READ_UNCOMMITTED = 1;
int TRANSACTION_READ_COMMITTED = 2;
int TRANSACTION_REPEATABLE_READ = 4;
int TRANSACTION_SERIALIZABLE = 8;