- 浏览: 16437 次
- 性别:
- 来自: 齐齐哈尔
最新评论
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,若没有采用必要的隔离机制,就会导致各种问题,这些病发问题可归纳为以下几类:
第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据股覆盖
脏读:一个事务读到另一事务未提交的更新数据
虚读:一个事务独到另一事务已提交的新插入的数据
不可重复读:一个事务读到另一事务已提交的更新数据
第二类丢失更新:这是不可重复读中的特例,一个事务覆盖另一事务已提交的个更新数据。
第一类丢失更新:这种并发是由于完全没有隔离事务造成的。当两个事务更新相同的数据资源,若一个事务被提交,另一个事务却被撤销,那么会连同第一个事务所做的更新也被撤销。
脏读:若第二个事务查询到第一个事务未提交的更新数据,第二个事务依据这个查询结果继续执行相关的操作,但接着第一个事务撤销了所做的更新,这导致第二个事务操纵脏数据。
虚读:由于一个事务查询到另一事务已提交的新插入的数据引起的。
不可重复读:由于一个事务查询到了另一个事务已提交的对数据的更新引起的。当第二个事务在某一时刻查询某条记录,在另一时刻在查询相同记录时,看到了第一个事务已提交的对这条记录的更新,第二个事务无法判断到底以哪一时刻查询到的记录作为计算基础。
第二类丢失更新:当两个或多个事务查询同样的记录,然后各自基于最初查询的结果更新记录时,会造成第二类丢失更新问题。每个事务都不知道其他事务的存在,最后一个事务对记录所做的更新将覆盖由其他事务对该记录所做的已提交的更新。
数据库系统的ACID特性中,隔离性就是指数据库系统必须具有隔离并发运行的各个事务的能力,使它们不会互相影响。数据库采用锁来实现事务的隔离性。锁的基本原理如下:
当一个事务访问某种数据库资源时,若执行select语句时,必须先获得共享锁;执行insert、update或delete语句时,也必须获得独占锁,此时根据已经放置在资源上的锁的类型,来决定第二个事务应该等待第一个事务接触对资源的锁定,还是可以立刻获得锁。
根据已放置在资源上的锁来决定第二个事务能否立刻获得特定类别的锁
资源上已经放置的锁 第二个事务进行读操作 第二个事务进行更新操作
无 立即获得共享锁 立即获得独占锁
共享锁 立即获得共享锁 等待第一个事务解除共享锁
独占锁 等待第一个事务解除独占锁 等待第一个事务解除独占锁
数据库系统能够锁定的资源包括:数据库、表、区域、页面、键值、行。按照锁定资源的粒度,锁可分为以下类型:
数据库级锁:锁定一战数据库表
表级锁:锁定一张数据库表
区域级锁:锁定数据库的特定区域
页面级锁:锁定数据库的特定页面
键值级锁:锁定数据库表中带有索引的一行数据
行级锁:锁定数据库表中的单行数据
锁的封锁粒度越大,事物间的隔离性就越高,事务间的并发性能就越低。
按照封锁程度,锁可分为:共享锁、独占锁和更新锁。
共享锁:用于读数据操作,允许其他事务同时读取其锁定的资源,但不允许其他事务更新它。有以下特征:
加锁的条件:当一个事务执行select语句时,数据库系统会为这个事务分配一把共享锁,来锁定被查询的数据。
解锁的条件:在默认的情况下,数据被读取后,数据库系统立即接触共享锁。
与其它锁的兼容性:若数据资源上放置了共享锁,还能在放置共享锁和更新锁
并发性能:具有良好的并发性能,当多个事务读相同的数据时,每个事物都会获得一把共享锁
独占锁:也叫排他锁,适用于修改数据的场合。它锁定的资源,其它事务不能读取,也不能修改。独占锁具有以下特征:
加锁的条件:当一个事务执行insert、update或delete语句时,数据库系统会自动对SQL语句操纵的数据资源使用独占锁。若该数据资源已经有其它锁存在时,无法对其再放置独占锁
解锁的条件:独占锁直到事务结束后才能被解锁
兼容性:独占所不能和其他锁兼容,若数据资源上已经加了独占锁,就不能再放置其他的锁。同样,若数据资源上已经有了其他的锁,就不能再放置独占锁
并发性能:并发性能较差,只允许有一个事务访问锁定的数据,若其他事务也需要访问该数据,就必须等待,直到前一个事务结束,解除了独占锁,其他事务才有机会访问该数据
更新锁:在更新操作的初始化阶段用来锁定可能要被修改的资源,可以避免使用共享锁造成的死锁现象。
若使用共享锁,更新数据的操作分为两步:
例: update ACCOUNTS set BALANCE=9000 where ID=1
获得一个共享锁,读取ACCOUNTS表中ID为1的记录
将共享锁升级为独占锁,在执行更新操作
若同时有两个或多个事务同时更新数据,每个事务都先获得一把共享锁,在更新数据的时候,这些事务都要先将共享锁升级为独占锁。由于独占锁不能和其他锁兼容,因此每个事务都进入等待状态,等待其他事务释放共享锁,这就造成了死锁。
若使用更新锁,更新数据的操作分为以下两步:
获得一个更新锁,读取ACCONTS表中ID为1的记录
将更新所升级为独占锁,在执行更新操作
更新锁有以下特征:
加锁的条件:当一个事务执行update语句时,数据库系统会先为事务分配一把更新锁
解锁的条件:当读取数据完毕,执行更新操作时,会把更新锁升级为独占锁
与其它锁的兼容性:更新锁与共享锁是兼容的,也就是说,一个资源可以同时放置更新锁和共享锁,但最多只能防止一把更新锁
并发性能:允许多个事务同时读锁定的资源,但不允许其他事务修改它
死锁:多个事务分别锁定一个资源,又试图请求锁定对方已经锁定的资源,导致多个事务处于等待对方释放锁定资源的状态
短事务:在一个数据库事务中包含尽可能少的操作,并且在尽可能短的时间内完成。
为实现短事务,在应用程序中可以考虑使用以下策略:
若可能的话尝试把大的事务分解为多个小的事务,然后分别执行,
应该在处理事务前就准备好用户必须提供的数据,不应该在执行事务过程中,停下来查过时间等待用户输入。
为了能让用户根据实际应用的需要,在事务的隔离性与并发性之间做合理的权衡,数据库系统提供了4种事务隔离级别供用户选择。
Serializable:串行化 隔离级别最高
Repeatable Read:可重复读
Read Committed:读已提交数据
Read Uncommitted:读未提交数据 隔离级别最低
各种隔离级别所能避免的并发问题
隔离级别 第一类丢失更新 脏读 虚读 不可重复读 第二类丢失更新
Serializeble 否 否 否 否 否
Repeatable Read 否 否 是 否 否
Read Committed 否 否 是 是 是
Read Uncommitted 否 是 是 是 是
Serializable:当数据库使用Serializable隔离级别时,一个事务在执行过程中完全看不到其他事务对数据库所做的更新。当两个事务同时操纵数据库中相同的数据时,若第一个事务已经在访问数据,第二个事务只能停下来,必读等到第一个事务结束后才能恢复运行
Repeatable Read:一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他事务对已有记录的更新
Read Committed:一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新
Read Uncommitted:一个事务在执行过程中个可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新
在mysql.exe程序中设置隔离级别
//查看当前的隔离级别
mysql>select @@tx_isolation
//设置(全局)隔离级别
mysql> set (global) transaction isolation level read committed
在应用程序中设置隔离级别
JDBC数据库连接使用数据库系统默认的隔离级别。在Hibernate的配置文件中以显式地设置隔离级别。每一种隔离级别都对应一个整数
1:Read Uncommitted
2:Read Committed
3:Repeatable Read
4:Seriliazable
hibernate.connection.isolation=2
当数据库系统采用Read Committed隔离级别时,会导致不可重复读和第二类丢失更新的并发问题。在可能出现这种问题的场合,可以子啊应用中采用悲观锁或乐观锁来避免这类问题。
悲观锁:在应用程序中显式地为数据资源加锁。悲观锁假定当前事务操纵数据资源时,肯定还会有其他事务同时访问该数据资源,为了避免当前事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类问题,但它会影响并发性能。
乐观锁:乐观所假定当前事务操纵数据资源时,不会有其他事务同时访问该数据源,因此完全依靠数据库的隔离级别来自动管理锁的工作。
悲观锁有两种实现方式:
方式一:在应用程序中显式指定采用数据库系统的独占锁来锁定数据资源
select ... for update
在Hibernate应用中,当通过Session的get()和load()方法来加载一个对象时,可以采用一下方式声明使用悲观锁
Account account = (Account)session.get(Account.class,new Long
(1),LockMode.UPgrATE);
LockMode类表示的几种锁定模式
锁定模式 描述
LodeMode.NONE(默认) 若在Hibernate的缓存中存在对象,就直接返回该对象的引用,否则就通过select语句到数据库中加载对象 不
LockMode.READ 不管Hibernate的缓存中是否存在对象,总是通过select语句到数据库中加载对象,若映射文件中设置了版本元素,比较缓存中的对象是否和数据库中的对象的版本一致
LockMode.UPGRADE 不管Hibernate的缓存中是否存在对象,总是通过select语句到数据库中加载对象,若映射文件中设置了版本元素,比较缓存中的对象是否和数据库中的对象的版本一致,若数据库系统支持悲观锁,就执行select ... for update语句,若不支持,就执行普通的select语句
LockMode.UPGRADE_NOWAIT 和LockMode.UPGRADE具有同样的功能。nowait表明执行该select语句的事务不能立即获得悲观锁,那么不会等待其他事务释放锁,而是立刻抛出以个锁定异常
LockMode.WRITE 当Hibernate向数据库保存一个对象时,会自动使用这种锁定模式,这种锁定模式仅供Hibernate内部使用,在应用程序中不应该使用
LockMode.FORCE 强制更新数据库中对象的版本属性,从而表明当前事务已经更新了这个对象
在Hibernate提供改的版本控制功能来实现乐观锁。对象-关系映射文件中的<version>元素和<timestamp>都具有版本控制功能。<version>元素利用一个递增的整数来跟踪数据库表中记录的版本,而<timestamp>元素用时间戳来跟踪数据库表红记录的版本。版本控制不具有级联性。
使用<version>元素
1.在ACCOUNT类中定义一个代表版本信息的属性
private int version;
public int getVersion(){
return this.version;
}
public int setVersion(int version){
this.version=version;
}
2.在ACCOUNTS表中定义一个代表版本信息的字段
create table ACCOUNTS{
ID bigint not null,
NAME varchar(15),
BALANCE decimal(10,2),
VERSION integer,
primary key(ID)
}type=INNODB
3.在Account.hbm.xml文件中用<version>元素来建立Account类的version属性与ACCOUNTS表中VERSION字段的映射
<id name="id" type="long" column="ID">
<generator class="increment">
</id>
//version必须紧跟在id后面
<version name="version" column="VERSION">
在应用程序中应该捕获StaleOjectStateException,这种异常有两种处理方式:
1.自动撤销事务,
2.通知用户信息已被其他事务修改,由用户决定如何继续事务
方式二:在数据库表中增加一个表明记录状态的LOCK字段,当它取值为'Y'时,表示该记录已经被某个事务锁定,若为'N',表明该记录处于空闲状态,事务可以访问它
使用<timestamp>元素,只能精确到秒
1.在ACCOUNT类中定义一个代表版本信息的属性
private Date lastUpdateTime;
public int getLastUpdateTime(){
return this.lastUpdateTime;
}
public int setLastUpdateTime(Date lastUpdateTime){
this.lastUpdateTime=lastUpdateTime;
}
2.在ACCOUNTS表中定义一个代表版本信息的字段
create table ACCOUNTS{
ID bigint not null,
NAME varchar(15),
BALANCE decimal(10,2),
LAST_UPDATE_TIME timestamp,
primary key(ID)
}type=INNODB
3.在Account.hbm.xml文件中用<version>元素来建立Account类的version属性与ACCOUNTS表中VERSION字段的映射
<id name="id" type="long" column="ID">
<generator class="increment">
</id>
//timestamp必须紧跟在id后面
<timestamp name="lastUpdateTime" column="LAST_UPDATE_TIME">
Session的lock()方法显式对一个有利对象进行版本控制
Session session1 = sessionFactory.openSession();
tx1 = session1.beginTransaction();
Account account = (Account)session1.get(Account.class,new Long(1));
tx1.commit();
session1.close();
account.setBalance(account.getBalance()-100);
Session session2 = sessionFactory.openSession();
tx2 = session2.beginTransaction();
session2.lock(account,LockMode.READ);
tx2.commit();
session2.close();
Session的lock()方法执行以下步骤:
把Account对象与当前Session关联。
若设定了LockMode.READ模式,就比较这个Account对象的版本是否与ACCOUNTS表中对应记录的版本一致。若不一致,说明ACCOUNTS表中对饮个记录已经被其他事务修改,因此会抛出StaleObjectStateException。
Hibernate提供了实现乐观所的办法。把<class>元素的optimistic-lock属性设为all。
若把optimistic-lock的属性设为all或dirty时,必须同时把dynamic-update属性设为true。这种方法速度慢,只是用于在一个Session中加载了对象,然后在同一个Session中修改这个持久化对象的场合。
第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据股覆盖
脏读:一个事务读到另一事务未提交的更新数据
虚读:一个事务独到另一事务已提交的新插入的数据
不可重复读:一个事务读到另一事务已提交的更新数据
第二类丢失更新:这是不可重复读中的特例,一个事务覆盖另一事务已提交的个更新数据。
第一类丢失更新:这种并发是由于完全没有隔离事务造成的。当两个事务更新相同的数据资源,若一个事务被提交,另一个事务却被撤销,那么会连同第一个事务所做的更新也被撤销。
脏读:若第二个事务查询到第一个事务未提交的更新数据,第二个事务依据这个查询结果继续执行相关的操作,但接着第一个事务撤销了所做的更新,这导致第二个事务操纵脏数据。
虚读:由于一个事务查询到另一事务已提交的新插入的数据引起的。
不可重复读:由于一个事务查询到了另一个事务已提交的对数据的更新引起的。当第二个事务在某一时刻查询某条记录,在另一时刻在查询相同记录时,看到了第一个事务已提交的对这条记录的更新,第二个事务无法判断到底以哪一时刻查询到的记录作为计算基础。
第二类丢失更新:当两个或多个事务查询同样的记录,然后各自基于最初查询的结果更新记录时,会造成第二类丢失更新问题。每个事务都不知道其他事务的存在,最后一个事务对记录所做的更新将覆盖由其他事务对该记录所做的已提交的更新。
数据库系统的ACID特性中,隔离性就是指数据库系统必须具有隔离并发运行的各个事务的能力,使它们不会互相影响。数据库采用锁来实现事务的隔离性。锁的基本原理如下:
当一个事务访问某种数据库资源时,若执行select语句时,必须先获得共享锁;执行insert、update或delete语句时,也必须获得独占锁,此时根据已经放置在资源上的锁的类型,来决定第二个事务应该等待第一个事务接触对资源的锁定,还是可以立刻获得锁。
根据已放置在资源上的锁来决定第二个事务能否立刻获得特定类别的锁
资源上已经放置的锁 第二个事务进行读操作 第二个事务进行更新操作
无 立即获得共享锁 立即获得独占锁
共享锁 立即获得共享锁 等待第一个事务解除共享锁
独占锁 等待第一个事务解除独占锁 等待第一个事务解除独占锁
数据库系统能够锁定的资源包括:数据库、表、区域、页面、键值、行。按照锁定资源的粒度,锁可分为以下类型:
数据库级锁:锁定一战数据库表
表级锁:锁定一张数据库表
区域级锁:锁定数据库的特定区域
页面级锁:锁定数据库的特定页面
键值级锁:锁定数据库表中带有索引的一行数据
行级锁:锁定数据库表中的单行数据
锁的封锁粒度越大,事物间的隔离性就越高,事务间的并发性能就越低。
按照封锁程度,锁可分为:共享锁、独占锁和更新锁。
共享锁:用于读数据操作,允许其他事务同时读取其锁定的资源,但不允许其他事务更新它。有以下特征:
加锁的条件:当一个事务执行select语句时,数据库系统会为这个事务分配一把共享锁,来锁定被查询的数据。
解锁的条件:在默认的情况下,数据被读取后,数据库系统立即接触共享锁。
与其它锁的兼容性:若数据资源上放置了共享锁,还能在放置共享锁和更新锁
并发性能:具有良好的并发性能,当多个事务读相同的数据时,每个事物都会获得一把共享锁
独占锁:也叫排他锁,适用于修改数据的场合。它锁定的资源,其它事务不能读取,也不能修改。独占锁具有以下特征:
加锁的条件:当一个事务执行insert、update或delete语句时,数据库系统会自动对SQL语句操纵的数据资源使用独占锁。若该数据资源已经有其它锁存在时,无法对其再放置独占锁
解锁的条件:独占锁直到事务结束后才能被解锁
兼容性:独占所不能和其他锁兼容,若数据资源上已经加了独占锁,就不能再放置其他的锁。同样,若数据资源上已经有了其他的锁,就不能再放置独占锁
并发性能:并发性能较差,只允许有一个事务访问锁定的数据,若其他事务也需要访问该数据,就必须等待,直到前一个事务结束,解除了独占锁,其他事务才有机会访问该数据
更新锁:在更新操作的初始化阶段用来锁定可能要被修改的资源,可以避免使用共享锁造成的死锁现象。
若使用共享锁,更新数据的操作分为两步:
例: update ACCOUNTS set BALANCE=9000 where ID=1
获得一个共享锁,读取ACCOUNTS表中ID为1的记录
将共享锁升级为独占锁,在执行更新操作
若同时有两个或多个事务同时更新数据,每个事务都先获得一把共享锁,在更新数据的时候,这些事务都要先将共享锁升级为独占锁。由于独占锁不能和其他锁兼容,因此每个事务都进入等待状态,等待其他事务释放共享锁,这就造成了死锁。
若使用更新锁,更新数据的操作分为以下两步:
获得一个更新锁,读取ACCONTS表中ID为1的记录
将更新所升级为独占锁,在执行更新操作
更新锁有以下特征:
加锁的条件:当一个事务执行update语句时,数据库系统会先为事务分配一把更新锁
解锁的条件:当读取数据完毕,执行更新操作时,会把更新锁升级为独占锁
与其它锁的兼容性:更新锁与共享锁是兼容的,也就是说,一个资源可以同时放置更新锁和共享锁,但最多只能防止一把更新锁
并发性能:允许多个事务同时读锁定的资源,但不允许其他事务修改它
死锁:多个事务分别锁定一个资源,又试图请求锁定对方已经锁定的资源,导致多个事务处于等待对方释放锁定资源的状态
短事务:在一个数据库事务中包含尽可能少的操作,并且在尽可能短的时间内完成。
为实现短事务,在应用程序中可以考虑使用以下策略:
若可能的话尝试把大的事务分解为多个小的事务,然后分别执行,
应该在处理事务前就准备好用户必须提供的数据,不应该在执行事务过程中,停下来查过时间等待用户输入。
为了能让用户根据实际应用的需要,在事务的隔离性与并发性之间做合理的权衡,数据库系统提供了4种事务隔离级别供用户选择。
Serializable:串行化 隔离级别最高
Repeatable Read:可重复读
Read Committed:读已提交数据
Read Uncommitted:读未提交数据 隔离级别最低
各种隔离级别所能避免的并发问题
隔离级别 第一类丢失更新 脏读 虚读 不可重复读 第二类丢失更新
Serializeble 否 否 否 否 否
Repeatable Read 否 否 是 否 否
Read Committed 否 否 是 是 是
Read Uncommitted 否 是 是 是 是
Serializable:当数据库使用Serializable隔离级别时,一个事务在执行过程中完全看不到其他事务对数据库所做的更新。当两个事务同时操纵数据库中相同的数据时,若第一个事务已经在访问数据,第二个事务只能停下来,必读等到第一个事务结束后才能恢复运行
Repeatable Read:一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他事务对已有记录的更新
Read Committed:一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新
Read Uncommitted:一个事务在执行过程中个可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新
在mysql.exe程序中设置隔离级别
//查看当前的隔离级别
mysql>select @@tx_isolation
//设置(全局)隔离级别
mysql> set (global) transaction isolation level read committed
在应用程序中设置隔离级别
JDBC数据库连接使用数据库系统默认的隔离级别。在Hibernate的配置文件中以显式地设置隔离级别。每一种隔离级别都对应一个整数
1:Read Uncommitted
2:Read Committed
3:Repeatable Read
4:Seriliazable
hibernate.connection.isolation=2
当数据库系统采用Read Committed隔离级别时,会导致不可重复读和第二类丢失更新的并发问题。在可能出现这种问题的场合,可以子啊应用中采用悲观锁或乐观锁来避免这类问题。
悲观锁:在应用程序中显式地为数据资源加锁。悲观锁假定当前事务操纵数据资源时,肯定还会有其他事务同时访问该数据资源,为了避免当前事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类问题,但它会影响并发性能。
乐观锁:乐观所假定当前事务操纵数据资源时,不会有其他事务同时访问该数据源,因此完全依靠数据库的隔离级别来自动管理锁的工作。
悲观锁有两种实现方式:
方式一:在应用程序中显式指定采用数据库系统的独占锁来锁定数据资源
select ... for update
在Hibernate应用中,当通过Session的get()和load()方法来加载一个对象时,可以采用一下方式声明使用悲观锁
Account account = (Account)session.get(Account.class,new Long
(1),LockMode.UPgrATE);
LockMode类表示的几种锁定模式
锁定模式 描述
LodeMode.NONE(默认) 若在Hibernate的缓存中存在对象,就直接返回该对象的引用,否则就通过select语句到数据库中加载对象 不
LockMode.READ 不管Hibernate的缓存中是否存在对象,总是通过select语句到数据库中加载对象,若映射文件中设置了版本元素,比较缓存中的对象是否和数据库中的对象的版本一致
LockMode.UPGRADE 不管Hibernate的缓存中是否存在对象,总是通过select语句到数据库中加载对象,若映射文件中设置了版本元素,比较缓存中的对象是否和数据库中的对象的版本一致,若数据库系统支持悲观锁,就执行select ... for update语句,若不支持,就执行普通的select语句
LockMode.UPGRADE_NOWAIT 和LockMode.UPGRADE具有同样的功能。nowait表明执行该select语句的事务不能立即获得悲观锁,那么不会等待其他事务释放锁,而是立刻抛出以个锁定异常
LockMode.WRITE 当Hibernate向数据库保存一个对象时,会自动使用这种锁定模式,这种锁定模式仅供Hibernate内部使用,在应用程序中不应该使用
LockMode.FORCE 强制更新数据库中对象的版本属性,从而表明当前事务已经更新了这个对象
在Hibernate提供改的版本控制功能来实现乐观锁。对象-关系映射文件中的<version>元素和<timestamp>都具有版本控制功能。<version>元素利用一个递增的整数来跟踪数据库表中记录的版本,而<timestamp>元素用时间戳来跟踪数据库表红记录的版本。版本控制不具有级联性。
使用<version>元素
1.在ACCOUNT类中定义一个代表版本信息的属性
private int version;
public int getVersion(){
return this.version;
}
public int setVersion(int version){
this.version=version;
}
2.在ACCOUNTS表中定义一个代表版本信息的字段
create table ACCOUNTS{
ID bigint not null,
NAME varchar(15),
BALANCE decimal(10,2),
VERSION integer,
primary key(ID)
}type=INNODB
3.在Account.hbm.xml文件中用<version>元素来建立Account类的version属性与ACCOUNTS表中VERSION字段的映射
<id name="id" type="long" column="ID">
<generator class="increment">
</id>
//version必须紧跟在id后面
<version name="version" column="VERSION">
在应用程序中应该捕获StaleOjectStateException,这种异常有两种处理方式:
1.自动撤销事务,
2.通知用户信息已被其他事务修改,由用户决定如何继续事务
方式二:在数据库表中增加一个表明记录状态的LOCK字段,当它取值为'Y'时,表示该记录已经被某个事务锁定,若为'N',表明该记录处于空闲状态,事务可以访问它
使用<timestamp>元素,只能精确到秒
1.在ACCOUNT类中定义一个代表版本信息的属性
private Date lastUpdateTime;
public int getLastUpdateTime(){
return this.lastUpdateTime;
}
public int setLastUpdateTime(Date lastUpdateTime){
this.lastUpdateTime=lastUpdateTime;
}
2.在ACCOUNTS表中定义一个代表版本信息的字段
create table ACCOUNTS{
ID bigint not null,
NAME varchar(15),
BALANCE decimal(10,2),
LAST_UPDATE_TIME timestamp,
primary key(ID)
}type=INNODB
3.在Account.hbm.xml文件中用<version>元素来建立Account类的version属性与ACCOUNTS表中VERSION字段的映射
<id name="id" type="long" column="ID">
<generator class="increment">
</id>
//timestamp必须紧跟在id后面
<timestamp name="lastUpdateTime" column="LAST_UPDATE_TIME">
Session的lock()方法显式对一个有利对象进行版本控制
Session session1 = sessionFactory.openSession();
tx1 = session1.beginTransaction();
Account account = (Account)session1.get(Account.class,new Long(1));
tx1.commit();
session1.close();
account.setBalance(account.getBalance()-100);
Session session2 = sessionFactory.openSession();
tx2 = session2.beginTransaction();
session2.lock(account,LockMode.READ);
tx2.commit();
session2.close();
Session的lock()方法执行以下步骤:
把Account对象与当前Session关联。
若设定了LockMode.READ模式,就比较这个Account对象的版本是否与ACCOUNTS表中对应记录的版本一致。若不一致,说明ACCOUNTS表中对饮个记录已经被其他事务修改,因此会抛出StaleObjectStateException。
Hibernate提供了实现乐观所的办法。把<class>元素的optimistic-lock属性设为all。
若把optimistic-lock的属性设为all或dirty时,必须同时把dynamic-update属性设为true。这种方法速度慢,只是用于在一个Session中加载了对象,然后在同一个Session中修改这个持久化对象的场合。
发表评论
-
Hibernate_11
2014-09-22 17:43 412缓存的物理介质通常是内存,而永久性数据存储源的物理介质通常是硬 ... -
Hibernate_9
2014-09-19 11:25 380数据库事务必须具备ACID特征,ACID是Atomic(原子性 ... -
Hibernate_8
2014-09-18 16:37 422Hibernate可以与任何一种Java应用的运行环境集成。J ... -
Hibernate_7
2014-09-17 16:55 697JDBC API提供了一种可滚动的结果集,它是利用数据库系统中 ... -
Hibernate_6
2014-09-15 17:51 527Java的集合类位于java.util包中,Java集合中存放 ... -
Hibernate_5
2014-09-12 19:22 403Hibernate映射类型分为两种:内置映射类型和客户化映射类 ... -
Hibernate_4
2014-09-06 10:39 457当程序通过Hibernate来加载、保存、更新或删除对象时,会 ... -
Hibernate_3
2014-09-04 17:52 354这几天心情不好,效率 ... -
Hibernate_2
2014-09-04 09:12 370hbm2ddl工具位于Hibernate核 ... -
Hibernate_1
2014-09-02 22:10 378分层体系结构: 逻辑上一般分为三层:表述层(提供与用户交互的界 ...
相关推荐
串流分屏 - 两台笔记本电脑屏幕共享
tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl
基于java的银行业务管理系统答辩PPT.pptx
TA_lib库(whl轮子),直接pip install安装即可,下载即用,非常方便,各个python版本对应的都有。 使用方法: 1、下载下来解压; 2、确保有python环境,命令行进入终端,cd到whl存放的目录,直接输入pip install TA_lib-xxxx.whl就可以安装,等待安装成功,即可使用! 优点:无需C++环境编译,下载即用,方便
"Turkish Law Dataset for LLM Finetuning" 是一个专为法律领域预训练的大型语言模型(LLM)微调而设计的数据集。这个数据集包含了大量的土耳其法律文本,旨在帮助语言模型更好地理解和处理土耳其法律相关的查询和文档。 该数据集的特点包括: 专业领域:专注于土耳其法律领域,提供了大量的法律文本和案例,使模型能够深入学习法律语言和术语。 大规模:数据集规模庞大,包含了超过1000万页的法律文档,总计约135.7GB的数据,这为模型提供了丰富的学习材料。 高质量:数据经过清洗和处理,去除了噪声和非句子文本,提高了数据质量,使得模型训练更加高效。 预训练与微调:数据集支持预训练和微调两个阶段,预训练阶段使用了大量的土耳其语网页数据,微调阶段则专注于法律领域,以提高模型在特定任务上的表现。 多任务应用:微调后的模型可以应用于多种法律相关的NLP任务,如法律文本摘要、标题生成、文本释义、问题回答和问题生成等。 总的来说,这个数据集为土耳其法律领域的自然语言处理研究提供了宝贵的资源,有助于推动土耳其语法律技术的发展,并为法律专业人士提供更精准的技术支持。通过微调,
农业信息化服务平台 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
tornado-6.1b2-cp36-cp36m-manylinux2010_i686.whl
计算机NLP_预训练模型文件
随心淘网管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
计算机汇编杂谈-理解其中的原理
基于java的藏区特产销售平台答辩PPT.pptx
本压缩包资源说明,你现在往下拉可以看到压缩包内容目录 我是批量上传的基于SpringBoot+Vue的项目,所以描述都一样;有源码有数据库脚本,系统都是测试过可运行的,看文件名即可区分项目~ |Java|SpringBoot|Vue|前后端分离| 开发语言:Java 框架:SpringBoot,Vue JDK版本:JDK1.8 数据库:MySQL 5.7+(推荐5.7,8.0也可以) 数据库工具:Navicat 开发软件: idea/eclipse(推荐idea) Maven包:Maven3.3.9+ 系统环境:Windows/Mac
安装包
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
Windows x64 操作系统上安装 Python 3.11 版本对应的dlib库,操作简单,无需pip在下载,再也不怕网络超时等其他不确定错误 使用方法: 1、确保windows x64系统上安装了python,可以用anaconda自带的python 2、确认python版本为3.11版本 3、下载资源解压为dlib-19.24.1-cp311-cp311-win_amd64.whl到本地,cd到对应目录,终端直接输入命令pip install dlib-19.24.1-cp311-cp311-win_amd64.whl 等待安装成功提示就可以用了,非常方便,有使用问题欢迎私信哟!
Jira插件安装包
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
tornado-6.1b2.tar.gz