1:事务(Transaction)
体现在整体的概念,要么事务中的操作全都失败,要么全多成功。。。
Eg:
(1):从Tom的账号上减去100元
(2):从Jack的账号上增加100元
2:数据库事务的生命周期
3:mysql的事务默认是自动提交的。
可以通过设置@@autocommit这个全局变量来变成手动提交
Select @@autocommit;
Result:1
Set @@autocommit = 0;//改成手动提交
4:数据库事务的4个特征:(ACID)
1):原子性(Atom)
2):一致性(Consistence)
3):隔离性(Isolation)
4):持久性(Duration)
5:多个事务并发运行时的并发访问问题
1):第一类丢失更新:撤销一个事务时,把其他事务应经提交的更新数据覆盖。
2):脏读:一个事务读到另一事务未提交的更新数据。
3)虚读:一个事务读到另一个事务已提交的新的插入的数据。
4):不可重复读:一个事务读到另一事务已提交的更新数据。
5):第二类丢失更新:这个是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据。
eg:
取款事务和支票转账事务
取款事务包含以下步骤:
-1:某银行客户在银行前台请求取款100元,出纳员先查询账号信息,得知存款余额为1000元。
-2:出纳员判断出存款金额超过了取款额,就支付给客户100元,并将账户上的存款余额改为900元。
支票转账事务包含以下步骤:
-1:某出纳员处理一转账支票,该支票向一账户汇入100元。出纳员先查询账户信息,得知存款余额为900元。
-2:出纳员将存款余额改为1000元。
eg:
并发运行的二个事务导致脏读
图片:
取款事务在T5时刻把存款余额改为900元,支票转账事务在T6时
刻查询账户的存款余额为900元,取款事务在T7时刻被撤销,支
票转账事务在T8时刻把存款余额改为1000元。
由于支票转账事务查询到了取款事务未提交的更新数据,并且在
这个查询结果的基础上进行更新操作,如果取款事务最后被撤销,
会导致银行客户损失100元。
并发的运行的二个事务导致第二类丢失更新
图片:
取款事务在T5时刻根据在T3时刻的查询结果,把存款
余额改为1000-100元,在T6时刻提交事务。支票转账
事务在T7时刻根据在T4时刻的查询结果,把存款余额
改为1000+100元。由于支票转账事务覆盖了取款事务
对存款余额所做的更新,导致银行最后损失100元。
6:数据库的事务隔离级别
隔离级别与并发性的关系:
设定隔离级别的原则:
1):隔离级别越高,越能保证数据的完整性和一致性,但是对并发的性能
的影响也会越大。
2:)对于多数的应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读,
而且具有较好的并发性能。尽管它会导致不可重复读,虚读,和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
在mysql.exe程序中设置隔离级别
每个数据库连接都会有一个全局变量@@tx_isolation,表示当前的事务隔离级别。MySql默认的隔离级别为Repeatable Reader。如果要查看当前的隔离级别,使用下面的Sql命令:
-mysql>select @@tx_isolation;
如果要把当前的mysql.exe程序的隔离级别改成Read Commmitted,使用如下命令:
-mysql>set transaction isolation level read committed;
7:在hibernate中设置隔离级别
-在hibernate的配置文件中可以显示的设置隔离的级别。
每一种隔离级别对应一种整数:
-1:Read Uncommitted
-2: Read Committed
-4:Repeatable Reader
-8:Serializable
eg:<property name="hibernate.connection.isolation">2</property>
8:悲观锁
Account account=(Account)session.get
(Account.class,new Long(1), LockMode.UPGRADE);
account.setBalance(account.getBalance()-100);
Hibernate执行的select语句为:
select * from ACCOUNTS where ID=1 for update;
update ACCOUNTS set BALANCE=900…
利用悲观锁协调并发运行的取款事务和支票转账事务
图片:
9:乐观锁(比悲观锁好)
• 乐观锁是由应用程序提供的一种机制,这种机制
既能保证多个事务并发访问数据,又能防止第二
类丢失更新问题。
• 在应用程序中,可以利用Hibernate提供的版本
控制功能来实现乐观锁。对象-关系映射文件中的
<version>元素和<timestamp>元素都具有版
本控制功能:
–<version>元素利用一个递增的整数来跟踪数据库表
中记录的版本
–<timestamp>元素用时间戳来跟踪数据库表中记录
的版本。