数据库事务中的基本概念
数据库事务是指,由一个或多个SQL语句组成的工作单元,这个工作单元中的SQL语句相互依赖,如果有一个SQL语句失败,那么整个操作都要撤销。在并发环境中,当多个事务同时访问同一资源时,可能会造成并发问题,此时可以使用数据库系统的事务隔离级别来避免各类并发问题。此外,在应用程序中还可以使用悲观锁和乐观锁来解决丢失更新的并发问题。
数据库事务必须具备ACID的特征(Atomic原子性,Consistency一致性,Isolation隔离性,Durability持久性)
原子性,指整个数据库事务是不可分割的单元。只有所有的语句执行成功,才算成功。
一致性,指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
隔离性,指在并发环境中,当不同的事务同时操作相同的数据时,每个事务都有各自的完整数据空间。
持久性,指的是只要事务成功结束,对数据库做的更新要永久保存下来.
Transaction和Session的关系,应该注意以下几点
Transaction的rollback()和Session的close()方法都会抛出HibernateException
不论事务是否成功,最后都应该关闭Session。
即使事务中只包含只读操作,也应该在事务成功执行之后提交事务,并且在事务执行失败时撤销事务,因为在提交或撤销事务时,数据库系统会释放占用的资源。
多个事务同时运行时的并发问题
第一类丢失更新,撤销一个事务时,把其他事务已提交的更新数据覆盖了。
脏读,一个事务读到另一个事务未提交的更新数据。
虚读,一个事务读到另一个事务已提交的新插入的数据。
不可重复读,一个事务读到另一个事务已提交的更新数据。
第二类更新,一个事务覆盖另一事务已提交的更新数据。
数据库系统锁的基本原理
按照锁定的资源的粒度,锁可以分为以下类型
数据库级锁: 锁定整个数据库
表级锁: 锁定一张表
区域级锁: 锁定数据库的特定区域
页面级锁: 锁定数据库的特定页面
见面级锁: 锁定数据库的特定页面
键值级锁: 锁定数据库表中带有索引的一行数据。
行级锁: 锁定数据库表中的但行数据(即一条记录)
按照封锁的程度,锁可以分为: 共享锁,独占锁,更新锁
共享锁, 共享锁用于读数据操作,它是非独占的,允许其他事务同时读取其锁定的资源,但不允许其他事务更新数据。共享锁的特征:
加锁条件:当一个事务执行Select操作时,数据库系统就会为其分配一把共享锁,来锁定查询数据。
解锁条件:在默认情况下,数据读取完毕,共享锁就解除了。
与其他锁的兼容性:如果数据资源上放置了共享锁,还能再放置共享锁和更新锁。
并发性能:具有良好的并发性能,当多个事务读相同的数据时,每个事务都会获得共享锁,因此可以同时读锁定的数据。
独占锁,也叫排它锁,适用于修改数据的场合。它锁定的资源,其他事务不能读取也不能更新。独占锁具有以下特征:
加锁的条件:当一个事务执行insert、update、或delete语句时,数据库就会为SQL所操作的数据使用独占锁。如果数据上有其他锁,那么就能放置独占锁.
解锁条件:到事务结束时才能被解除
与其他锁的兼容性:独占锁不能和其他锁兼容。通用如果资源上有其他锁,那么也不能放置独占锁。
并发性能:性能较差,只允许有一个事务访问锁定的数据,如果其他事务也需要访问该数据,就必须等待,直到前一个事务结束,解除了独占锁,其他事务才有机会访问资源。
更新锁,在更新操作的初始化阶段用来锁定可能要被修改的资源,这可以避免使用共享锁造成死锁的现象。更新具有以下特征:
加锁的条件:当一个事务执行update语句时,数据库系统会先为事务分配一把更新锁。
解锁条件:读取数据完毕,执行更新操作时,会把更新锁升级为独占锁。
与其他锁的兼容性:更新锁与共享锁是兼容的。也就是说,一个资源可以同时放置更新锁和共享锁,但是最多只能放置一把更新锁。
并发性能:允许多个事务同时访问资源。但不允许修改。
死锁及其防止方法
合理安排表的访问顺序
使用短事务。将大事务分割为多个小事务执行。应该在处理事务之前就准备好用户必须提供的数据。
如果对数据的一致性要求不高,可以允许脏度。
如果可能,错开多个事务访问相同数据资源的时间,以防止锁冲突。
使用尽可能低的事务级别。
数据库的隔离级别
尽管数据库系统允许用户在事务中显示的为数据资源加锁,但是首先应该考虑让数据库系统自动管理锁,它会分析事务中的SQL语句,然后自动为SQL语句所操作的数据资源加上合适的锁,而且在锁的数目太多时,数据库系统会自动的进行锁升级,以提供系统性能。
数据库系统提供了四种事务隔离级别供用户选择:
Serializable,串行化。
一个事务在执行过程中完全看不到事务对数据库所做的更新。当两个事务同时操作数据库中的数据时,如果第一个事务已经在访问该数据,那么第二个事务只能停下来等待。
Repeatable Read:可重复读
一个事务在执行过程中可以看到其他事务已经提交的新插入的数据。但是不能看到其他事务对已有数据做的跟新。
Read Commited:读已提交数据
一个事务在执行过程中可以看到其他事务已经提交的新插入的数据。可以看到其他对已有数据进行的更新。
Read UnCommited:读取未提交
一个事务可以看到,其他事务没有提交新插入的数据。而且更新操作的记录也能看到。
//: 在hibernate.cfg.xml中配置
hibernate.connection.isolation=2
在应用程序中才用悲观锁和乐观锁
悲观锁与乐观锁的概念
悲观锁,在应用程序中显示的为数据资源加锁。可以防止丢失更新和不可重复读问题。但是会影响性能。
乐观锁,假设当前的事务操作的数据,不会有其他事务同时访问该数据资源,完全依靠数据库系统自动管理锁。因此可能会出现并发问题。
利用数据库系统的独占锁来实现悲观锁
悲观锁的两种实现方式
应用中显示的指定采用数据库系统的独占锁来锁定数据资源。
在数据库表中增加一个表明记录状态的LOCK字段,当它取值为Y时,表示该i记录已被某个事务锁定。如果为N,表示该条数据为空闲状态。
在Hibernate中,当通过Session的get()和load()方式来加载一个对象时,可以采用以下方式使用悲观锁:
Customer cus = (Customer)session.get(Customer.class, "c001", LockMode.UPGRADE); //: final org.hibernate.LockMode
LockMode类表示的几种锁定模式
锁定模式 描述
LockMode.NONE 如果在Hibernate缓存中存在Customer对象,就直接返回该引用。否则通过select加载。默认值
LockMode.READ 不管缓存中是否有,都使用select加载数据。如果映射文件设置了版本元素,就执行版本检查,比较缓存中的与取到的是否版本一致。
LockMode.UPGRADE 不管缓存中是否有,都使用select加载数据。就执行版本检查,比较缓存中的与取到的是否版本一致。如果数据库系统支持悲观锁,那么执行select…for update, 否则执行简单的select
LockMode.UPGRADE_NOWAIT 会执行LockMode.UPGRADE和它一样的功能。若果执行的select不能立即获得悲观锁,那么就会抛出异常
LockMode.WRITE 当Hibernate保存或更新对象时,会自动使用这种锁定模式。这种锁定模式只在Hibernate内部使用,所以在应用中不应该使用它
利用Hibernate的版本控制来实现乐观锁
create table Accounts (
id bigint primary key,
name varchar(15),
balance numeric(10,2),
LAST_UPDATED_TIME timestamp,
version int
)
在hbm中配置版本控制
//: 在元素必须跟在<id>元素的后面
<version name = "version" column = "VERSION" />
//: 使用该元素也可以实现版本控制
<timestamp name=”lastUpdateTime” column=” LAST_UPDATED_TIME” />
对游离对象进行版本检查
Session session1 = ....;
trans1 = session1.beginTransaction();
Account a = (Account)session1.get(Account.class, new Long(1));
trans1.commit();
session1.close();
a.setBalance(a.getBalance()-100);
Session session2 = ...;
trans2 = session2.beginTransaction();
session2.lock(a, LockMode.READ);
trans2.commit();
session2.close();
lock() 方法和update()方法之间的区别
lock()方法在LockMode.READ模式下,立即进行版本控制。而update()方法不会立即执行版本检查,只有当Session清理缓存时,真正执行update时才进行版本检查
lock()在默认的LockMode中不会执行update语句。而update()会计划执行一个update语句,如果数据库中没对应的记录那么会抛出异常。
实现乐观锁的其他方式
<class optimistic-lock="all" dynamic-update="true">
//: optimistic-lock=all/dirty 时必须设置dynamic-update为true
分享到:
相关推荐
在第14部分,我们将深入探讨如何在Hibernate中执行查询以及如何管理数据库事务,特别是在并发环境中。 **描述:**描述为空,但我们可以推测博客内容可能包含实际示例、最佳实践以及对Hibernate查询API和事务管理...
数据库事务是数据库操作的核心组成部分,它确保了数据的一致性和完整性。事务是由一系列数据库操作组成的逻辑单元,这些操作要么全部成功执行,要么全部不执行,遵循ACID(原子性、一致性、隔离性和持久性)原则。 ...
本文将深入探讨Hibernate中的事务和并发控制,这对于开发高效、稳定的数据库应用至关重要。 首先,我们来理解Hibernate中的事务管理。在数据库操作中,事务是保证数据一致性的重要手段。一个事务包含了一组数据库...
事务和并发控制是数据库管理中的核心概念,特别是在使用ORM框架如Hibernate时,理解它们的工作原理至关重要。本文将深入探讨Hibernate中的事务管理和并发控制。 首先,事务是数据库操作的基本单位,它保证了数据的...
### 数据库事务总结 #### 一、事务的基本概念与特性 **事务**是数据库系统中的一个逻辑工作单元,它由一系列的操作组成,这些操作要么都完成,要么都不完成,以此来保证数据的一致性和完整性。 #### 二、事务的...
#### 三、事务并发处理 Hibernate 提供了两种主要的并发控制机制: 1. **乐观锁(Optimistic Locking)**:假设数据不会经常冲突,只有在提交时才会进行冲突检测。Hibernate 通过版本字段实现自动乐观并发控制。 2....
在Hibernate中,事务、并发控制和缓存管理是至关重要的概念,它们极大地影响了应用程序的性能和数据一致性。 一、Hibernate事务管理 在数据库操作中,事务确保了数据的一致性和完整性。Hibernate提供了四种事务隔离...
4. 事务配置:可能包含关于瀚高数据库事务特性的配置,如默认的事务隔离级别。 5. 其他辅助类:如序列生成器(Sequence Generator),用于在瀚高数据库中生成主键。 在实际应用中,开发者需要在Hibernate配置文件中...
标题:“Hibernate的事务与并发控制” 描述:本文深入解析了Hibernate框架中事务管理和并发控制的核心概念及其实现机制,基于一份详尽的“hibernate详细解析.pdf”文档,覆盖了非托管环境、JTA环境下的事务处理以及...
- 数据库事务和并发控制:理解ACID属性,以及乐观锁和悲观锁的概念。 2. **Hibernate ORM框架**: - Hibernate架构:介绍Session、SessionFactory和Transaction的概念,理解它们在ORM中的角色。 - 映射配置:...
《Hibernate的事务和并发资料》深入探讨了在Java应用程序中使用Hibernate进行事务管理和并发...开发者应熟悉JDBC、SQL和数据库事务隔离级别,以及如何通过合理配置和编程实践来优化并发性能,以适应不同的应用场景。
理想的做法是将数据库操作分组为原子性的操作单元,这些操作单元对应于数据库事务。在多用户客户端/服务器应用中,最常用的模式是“session-per-request”,即每个客户端请求对应一个Session,所有的数据库操作都在...
理解并熟练运用Hibernate的事务并发处理机制,可以帮助我们设计出更高效、更可靠的数据库访问层。在实际项目中,需要根据业务需求和并发量来灵活选择悲观锁或乐观锁,或者结合两者以达到最佳效果。同时,还要注意...
Hibernate 对事务并发处理 在 Hibernate 中,对事务并发处理是非常重要的, especialmente 在多用户环境中。事务处理的目的是为了保证数据的可靠性和一致性。 事务四个特性 ACID 1. 原子性(Atomicity):事务...
在Java的持久化框架Hibernate中,版本管理机制是实现事务并发控制的重要手段。它通过维护对象的版本信息,确保在多线程环境下数据的一致性和完整性。本文将深入探讨Hibernate中的版本管理机制及其在控制事务并发中的...