数据库--事务

来源:互联网 发布:索尼sd卡数据恢复 编辑:程序博客网 时间:2024/05/20 19:30

事务

一.事务

1. 事务介绍

Ø 什么是事务

事务,一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元。这些单元要么全都成功,要么全都不成功。

Ø 事务在开发中的作用

下面我们来举例说明什么是事务,如下所示:

现实生活中的银行转账业务,张三要给李四转账1000元,而在程序员眼中两条SQL语句就可以搞定,如下:

给张三的账户减去1000元;

给李四的账户加上1000元;

如果在转账的业务中,成功的将张三的账户减去1000元,而在给李四的账户加1000元的时候,程序出现了问题,李四的账户没有加上1000元,而张三的账户却减掉了1000元,在现实生活中,这种情况肯定是不允许存在的。当我们将这个转账业务放在一个事务中,就不会出现以上情况了。

事务中有多个操作,这些操作要么全部成功,要么全部失败,也就是说给张三的账户减去1000元如果成功了,那么给李四的账户加上1000元的操作也必须是成功的,否则给张三减去1000元,以及给李四加上1000元都必须是失败的

2. mysql中的事务

Ø mysql中默认事务处理

mysql登录的情况下执行以下命令

show variables like '%commit%'; ---- autocommint 值是 on,说明开启自动提交

 

mysql数据库默认是开启事务的,一条sql一个事务.

oracle它默认情况下autocommitoff,就需要手动提交事务.

 

关闭mysql的自动事务处理命令

set autocommit = off;( set autocommit = 0)

如果设置autocommit off,意味着以后每条SQL都会处于同一个事务中,相当于第一条SQL执行前执行了 start transaction

Ø mysql中手动事务处理

start transaction:-- 开启事务 一旦手动开启了事务,事务自动提交失效.

commit;-- 提交事务

rollback;-- 事务回滚

3. jdbc中的事务

Ø jdbc中事务处理api

java.sql.Connection接口中提供了关于事务操作的API

u ØsetAutoCommit(boolean flag); 参数为false相当于start transaction

u Øcommit(); 事务提交

u Ørollback(); 事务回滚

回滚(Rollback)指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为

Ø 回滚点介绍

ØSavepoint setSavepoint(String name)

在当前事务中创建一个具有给定名称的保存点,并返回表示它的新 Savepoint 对象。

例如:

Savepoint sp = conn.setSavepoint();

Conn.rollback(sp);

4. 事务的特性

事务的四大特性是面试官经常问的问题,简称ACID(Atomicity Consistency Isolation Durability),分别是:

u l原子性:原子性对应的英文是Atomicity,即表示事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败;

u l一致性:一致性对应的英文是Consistency,事务执行后,数据库状态与其它业务规则保持一致。例如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的;

u l隔离性:隔离性对应的英文是Isolation,是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰;

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

不同的事务,其一致性的表现形式是不同的,事务的其他三大特性其实都是为了事务的一致性服务的。

5. 事务的隔离级别与问题

Ø 不考虑隔离性产生的问题介绍

u n脏读 一个事务读取到了另一个事务未提交数据.

u n不可重复读 一个事务内,两次读取到的数据不一致.(update)

u n虚读(幻读)两次读取的数据不一致(insert)

Ø 事务的4种隔离级别介绍

数据库内部定义了四种隔离级别,用于解决三种隔离问题

1 Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)

2 Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)不可以避免虚读

3 Read committed:可避免脏读情况发生(读已提交)

4 Read uncommitted:最低级别,以上情况均无法保证。(读未提交)

mysql数据库默认的事务隔离级别-----repeatable read级别.

oracle数据默认的事务隔离级别 ----read committed

Ø 设置事务隔离级别

nmysql中设置

数据库默认有事务的隔离级别,mysql 中查看与修改事务的隔离级别

u set session transaction isolation level 隔离级别;设置事务隔离级别

u select @@tx_isolation; 查询当前事务隔离级别

 

njdbc中设置事务隔离级别

java.sql.Connection接口中提供

u setTransactionIsolation(int level) ;

参数可以取 Connection 常量之一:

Connection.TRANSACTION_READ_UNCOMMITTED

Connection.TRANSACTION_READ_COMMITTED

Connection.TRANSACTION_REPEATABLE_READ

Connection.TRANSACTION_SERIALIZABLE

(注意,不能使用 Connection.TRANSACTION_NONE,因为它指定了不受支持的事务。)

6. 演示设置隔离级别来解决问题

Ø 脏读分析与解决

脏读:一个事务读取到另一个事务未提交数据.

1.打开两个窗口 A  B

2.A窗口中设置事务的隔离级别为Read uncommitted

3.A窗口中设置事务的隔离级别为Read uncommitted

4.A窗口中开启事务,将aaa---bbb  500

5.B窗口查看account表中数据,,发现可以查看 到A窗口中的未提交的事务  操作结果。就出现了脏读。

 

解决脏读  设置事务的隔离级别为 read committed

Ø 不可重复读分析与解决

在上面的例子基础上操作,当我们将事务的隔离级别设置 read committed时,B窗口在查询时,就没有查询到A窗口未提交的数据,解决了脏读。

1.A窗口将数据提交

2.这时B窗口之前查询过一次,再次查询,这时就发现,我们在一个事务中两次查询结果不一致,就出现了不可重复读。

 

解决不可重复读  设置事务的隔离级别为  Repeatable read

Ø 虚读分析

它主要强调的是多次查询的结果的条不一样,而不可重复读强调的是结果不一样。

Ø 串行化演示

设置隔离级别为 Serializable

 

Ø 注意

对于隔离级别四种

安全性  Serializable>Repeatable read>read committed >read uncommitted;

性能    Serializable<Repeatable read<read committed <read uncommitted;

在开发中,一般使用  read committed  repeatable read两种。

7. 案例-转账汇款

Ø 功能描述

实现帐户之间转账操作,在创建一个account.jsp页面,在页面上有三个文本框,分别是转款人,收款人及金额,提交到服务器端,服务器端调用jdbc完成汇款操作。

我们采用web三层架构

涉及到的页面与类

Web层   account.jsp  AccountServlet

Service层  AccoountService

Dao层   AccountDao

Ø 案例分析

 

注意:

service层中使用事务

Ø 代码实现

8. 案例-使用ThreadLocal解决转账汇款问题

ThreadLocal介绍与原理分析

public class ThreadLocal<T>extends Object

该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 getset方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal实例通常是类中的private static字段,它们希望将状态与某一个线程(例如,用户ID或事务ID)相关联。

它的底层是使用了一个Map集合

Map<Thread,Object>

它的key就是当前的线程对象.

set(Object obj) 它就相当于  map.put(Thread.currentThread(),obj);

get()它就相当于 map.get(Thread.currentThread()));