事务

问题:事务是什么,有什么用?

事务就是一个事情,组成这个事情可能有多个单元,要求这些单元,要么全都成功,要么全都不成功。

在开发中,有事务的存在,可以保证数据完整性。

问题:事务怎样操作

创建表:

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);

1.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;

2.jdbc下怎样操作

java.sql.Connection接口中有几个方法是用于可以操作事务

1.setAutocommit(boolean flag);

如果flag=false;它就相当于start transaction;

2.rollBack()

事务回滚。

3.commit()

事务提交


事务特性(重点) ACID

? 原子性(Atomicity)

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

? 一致性(Consistency)

事务前后数据的完整性必须保持一致。

? 隔离性(Isolation)

事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

? 持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

-------------------------------------

如果不考虑事务的隔离性,会出现什么问题?

1.脏读 一个事务读取到另一个事务的未提交数据。

2.不可重复读

两次读取的数据不一致(update)

3.虚读(幻读)

两次读取的数据一一致(insert)

4.丢失更新

两个事务对同一条记录进行操作,后提交的事务,将先提交的事务的修改覆盖了。

-----------------------------------------

演示以上问题,以及问题的解决方案

对于以上的问题,我们可以通过设置事务的隔离级别来解决。

1.事务的隔离级别有哪些?

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

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

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

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

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

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可以取以下值:

level - 以下 Connection 常量之一:

Connection.TRANSACTION_READ_UNCOMMITTED、

Connection.TRANSACTION_READ_COMMITTED、

Connection.TRANSACTION_REPEATABLE_READ

Connection.TRANSACTION_SERIALIZABLE。

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

--------------------------------------------------

3.演示

1.脏读

一个事务读取到另一个事务的为提交数据

设置A,B事务隔离级别为  Read uncommitted

set session transaction isolation level  read uncommitted;

1.在A事务中

start transaction;

update account set money=money-500 where name='aaa';

update account set money=money+500 where name='bbb';

2.在B事务中

start transaction;

select * from account;

这时,B事务读取时,会发现,钱已经汇完。那么就出现了脏读。

当A事务提交前,执行rollback,在commit, B事务在查询,就会发现,钱恢复成原样

也出现了两次查询结果不一致问题,出现了不可重复读.

2.解决脏读问题

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

设置A,B事务隔离级别为  Read committed

set session transaction isolation level  read committed;

1.在A事务中

start transaction;

update account set money=money-500 where name='aaa';

update account set money=money+500 where name='bbb';

2.在B事务中

start transaction;

select * from account;

这时B事务中,读取信息时,是不能读到A事务未提交的数据的,也就解决了脏读。

让A事务,提交数据 commit;

这时,在查询,这次结果与上一次查询结果又不一样了,还存在不可重复读。

3.解决不可重复读

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

设置A,B事务隔离级别为  Repeatable read;

set session transaction isolation level  Repeatable read;

1.在A事务中

start transaction;

update account set money=money-500 where name='aaa';

update account set money=money+500 where name='bbb';

2.在B事务中

start transaction;

select * from account;

当A事务提交后commit;B事务在查询,与上次查询结果一致,解决了不可重复读。

4.设置事务隔离级别 Serializable ,它可以解决所有问题

set session transaction isolation level Serializable;

如果设置成这种隔离级别,那么会出现锁表。也就是说,一个事务在对表进行操作时,

其它事务操作不了。

--------------------------------------------------

总结:

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

不可重复读:两次读取数据不一致(读提交数据)---update

虚读:两次读取数据不一致(读提交数据)----insert

事务隔离级别:

read uncommitted 什么问题也解决不了.

read committed 可以解决脏读,其它解决不了.

Repeatable read 可以解决脏读,可以解决不可重复读,不能解决虚读.

Serializable 它会锁表,可以解决所有问题.

安全性:serializable > repeatable read > read committed > read uncommitted

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

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

mysql默认隔离级别 repeatable read ,oracle默认隔离级别 read committed


==========================================================================================

案例:转账汇款----使用事务

问题:service调用了dao中两个方法完成了一个业务操作,如果其中一个方法执行失败怎样办?

需要事务控制

问题:怎样进行事务控制?

我们在service层进行事务的开启,回滚以及提交操作。

问题:进行事务操作需要使用Connection对象,那么,怎样保证,在service中与dao中所使用的是同一个Connection.

在service层创建出Connection对象,将这个对象传递到dao层.

注意:Connecton对象使用完成后,在service层的finally中关闭

而每一个PreparedStatement它们在dao层的方法中用完就关闭.

关于程序问题

1.对于转入与转出操作,我们需要判断是否成功,如果失败了,可以通过抛出自定义异常在servlet中判断,

进行信息展示 。

----------------------------------------------------------问题:在设置dao层时,public interface AccountDao {public void accountOut(String accountOut, double money) throws Exception;public void accountIn(String accountIn, double money) throws Exception;}那么我们自己去实现这个接口时,怎样处理,同一个Connection对象问题?使用ThreadLocalThreadLocal可以理解成是一个Map集合Mapset方法是向ThreadLocal中存储数据,那么当前的key值就是当前线程对象.get方法是从ThreadLocal中获取数据,它是根据当前线程对象来获取值。如果我们是在同一个线程中,只要在任意的一个位置存储了数据,在其它位置上,就可以获取到这个数据。关于JdbcUtils中使用ThreadLocal1.声明一个ThreadLocalprivate static final ThreadLocaltl = new ThreadLocal();

2.在getConnection()方法中操作

Connection con = tl.get(); 直接从ThreadLocal中获取,第一次返回的是null.

if (con == null) {

// 2.获取连接

con = DriverManager.getConnection(URL, USERNAME, PASSWORD);

tl.set(con); //将con装入到ThreadLocal中。

}

==========================================================================================

丢失更新

多个事务对同一条记录进行了操作,后提交的事务将先提交的事务操作覆盖了。

查看图.

问题:怎样解决丢失更新问题?

解决丢失更新可以采用两种方式:

1.悲观锁

悲观锁 (假设丢失更新一定会发生 ) ----- 利用数据库内部锁机制,管理事务

提供的锁机制

1.共享锁

select * from table lock in share mode(读锁、共享锁)

2.排它锁

select * from table for update (写锁、排它锁)

update语句默认添加排它锁

2.乐观锁

乐观锁 (假设丢失更新不会发生)------- 采用程序中添加版本字段解决丢失更新问题

create table product (

id int,

name varchar(20),

updatetime timestamp

);

insert into product values(1,'冰箱',null);

update product set name='洗衣机' where id = 1;

解决丢失更新:在数据表添加版本字段,每次修改过记录后,版本字段都会更新,如果读取是版本字段,

与修改时版本字段不一致,说明别人进行修改过数据 (重改)

===============================================================================================================

连接池 问题:连接池是什么,有什么用?

连接池:就是创建一个容器,用于装入多个Connection对象,在使用连接对象时,从容器中获取一个Connection,  使用完成后,在将这个Connection重新装入到容器中。这个容器就是连接池。(DataSource)  也叫做数据源.  我们可以通过连接池获取连接对象.优点:节省创建连接与释放连接 性能消耗 ---- 连接池中连接起到复用的作用 ,提高程序性能-----------------------------------------------------------------------------------自定义连接池

1.创建一个MyDataSource类,在这个类中创建一个LinkedList

2.在其构造方法中初始化List集合,并向其中装入5个Connection对象。

3.创建一个public Connection getConnection();从List集合中获取一个连接对象返回.

4.创建一个  public void readd(Connection) 这个方法是将使用完成后的Connection对象重新装入到List集合中.

代码问题:

1.连接池的创建是有标准的.

在javax.sql包下定义了一个接口 DataSource

简单说,所有的连接池必须实现javax.sql.DataSource接口,

我们的自定义连接池必须实现DataSource接口。

2.我们操作时,要使用标准,怎样可以让 con.close()它不是销毁,而是将其重新装入到连接池.

要解决这个问题,其本质就是将Connection中的close()方法的行为改变。

怎样可以改变一个方法的行为(对方法功能进行增强)

1.继承

2.装饰模式

1.装饰类与被装饰类要实现同一个接口或继承同一个父类

2.在装饰类中持有一个被装饰类引用

3.对方法进行功能增强。

3.动态代理

可以对行为增强

Proxy.newProxyInstance(ClassLoacer ,Class[],InvocationHandler);

结论:Connection对象如果是从连接池中获取到的,那么它的close方法的行为已经改变了,不在是销毁,而是重新装入到连接池。

--------------------------------------------------------------------

1.连接池必须实现javax.sql.DataSource接口。

2.要通过连接池获取连接对象  DataSource接口中有一个  getConnection方法.

3.将Connection重新装入到连接池  使用Connection的close()方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • 一、什么是事务 逻辑上的一组操作, ,要不全部失败,要不全部成功。 MySql的事务管理 在事务管理中执行sql,...
    明天你好向前奔跑阅读 792评论 0 4
  • 一、事务 事务就是一个事情,组成这个事情可能有多个单元,要求这些单元,要么全都成功,要么全都不成功。在开发中,有事...
    野狗子嗷嗷嗷阅读 2,787评论 0 6
  • 本文包括:1、事务概念2、MySQL管理事务3、JDBC控制事务进程4、事务的特性(ACID)5、事务的隔离级别6...
    廖少少阅读 821评论 0 3
  • 很多人喜欢这篇文章,特此同步过来 由浅入深谈论spring事务 前言 这篇其实也要归纳到《常识》系列中,但这重点又...
    码农戏码阅读 4,687评论 2 59
  • 事务 1.事务的概念: 事务是指逻辑上的一组操作,这组操作要么同时完成要么同时不完成。参考转账操作。 2. 如果你...
    PASSssss阅读 285评论 0 0