mysql innodb 事务隔离级别_mysql InnoDB的事务隔离级别与hibernate的使用

mysql

InnoDB支持四类事务隔离级别,同时还支持一致性读操作,也就是单独的select语句不受事务影响,不会对数据库记录加锁,除非是在serializable级别,该语句会默认转为select

... lock in share mode; 在这种模式下会对数据库表加意向共享锁,同时对单独的记录加共享锁。

在mysql中只有两种select语句加锁,select ... lock in share mode;和select ...

for update;第一个是对表加意向共享锁,对记录索引加共享锁,第二类是对表加意向排他锁,对记录索引加排他锁。

要点:

(1)mysql对表加意向锁

(2)mysql对记录索引加锁,不是对记录本身

(3)mysql有可能对扫描过的索引范围加锁,而不是单独某个索引。

(4)锁的相容和排斥性。

X

IX

S

IS

X

冲突

冲突

冲突

冲突

IX

冲突

兼容

冲突

兼容

S

冲突

冲突

兼容

兼容

IS

冲突

兼容

兼容

兼容

(5)参见mysql手册第15章关于InnoDB引擎的描述。

InnoDB中每个隔离级别的详细描述如下:

·

READ UNCOMMITTED

SELECT语句以非锁定方式被执行,但是一个可能更早期版本的记录会被用到。因此,使用这个隔离级别,比如,读是不连贯的。着也被称为“脏读”(dirty

read)。另外,这个隔离级别象READ COMMITTED一样作用。

·

READ COMMITTED

一个有些象Oracle的隔离级别。所有SELECT ... FOR UPDATE和SELECT ... LOCK

IN SHARE

MOD语句仅锁定索引记录,而不锁定记录前的间隙,因而允许随意紧挨着已锁定的记录插入新记录。UPDATE和DELETE语句使用一个带唯一搜索条件的唯一的索引仅锁定找到的索引记录,而不包括记录前的间隙。在范围类型UPDATE和DELETE语句,InnoDB必须对范围覆盖的间隙设置next-key锁定或间隙锁定以及其它用户做的块插入。这是很必要的,因为要让MySQL复制和恢复起作用,“幽灵行”必须被阻止掉。

持续读行为如同在Oracle中:即使在同一事务内, 每个持续读设置并读取它自己的新快照。请参阅15.2.10.4节,“持续非锁定读”。

·

REPEATABLE READ

这是InnoDB的默认隔离级别。带唯一搜索条件使用唯一索引的SELECT ... FOR UPDATE,

SELECT ... LOCK IN SHARE MODE, UPDATE

和DELETE语句只锁定找到的索引记录,而不锁定记录前的间隙。用其它搜索条件,这些操作采用next-key锁定,用next-key锁定或者间隙锁定锁住搜索的索引范围,并且阻止其它用户的新插入。

在持续读中,有一个与之前隔离级别重要的差别:在这个级别,在同一事务内所有持续读读取由第一次读所确定的同一快照。这个惯例意味着如果你在同一事务内发出数个无格式SELECT语句,这些SELECT语句对相互之间也是持续的,请参阅15.2.10.4节,“持续非锁定读”。

·

SERIALIZABLE

这个级别类似REPEATABLE READ,但是所有无格式SELECT语句被隐式转换成SELECT ... LOCK

IN SHARE MODE。

因此mysql端的事务已经了解清楚。

那么hibernate是如何使用的呢?

(1)hibernate默认使用mysql的事务隔离级别,不过也可以在配置文件中配置,如设置

hibernate.connection.isolation=8表示使用serializable级别,其中1,2,4级别分别表示前三个。

(2)hibernate的update语句默认不执行,除非显示调用session.flush()方法才可以。本人在实验中一开始就忽视了这个问题,以为update语句执行后就对数据库记录加了锁,其实没有显示到数据库中。

(3)hibernate的LockMode.UPGRADE锁定模式,会生成for update的查询语句。

(4)可以使用SQLQuery语句,直接写for update语句。

因此,hibernate操作mysql的事务隔离级别一般可以这样选择:

(1)一般选用mysql默认事务隔离级别即可,即repeatable

read级别,此时,如果是查询数据,而防止在查询的同时,其他事务插入或更新数据,则选用select lock in share

mode语句;如果是更新数据,防止死锁,则选用select .... for update语句。

(2)具体事务中,要尽量减少操作两个表,如一个事务中先锁定A表,再锁定B表,另一个事务中先锁定B表,再锁定A表,这样则容易发生死锁,虽然mysql可以通过回退一个事务来避免死锁,但在程序中尽量避免这种情况出现。一种避免方式如下:

在一个事务中都是按一个顺序获取表的锁,另外,尽量都获取排他锁,这样子,事务之间就可以实现串行化,不会出现死锁现象。

总结:

我在hibernate配置问题中配置了hibernate.connection.isolation属性,并且属性值为2,这个问题就算解决了

name="hibernate.connection.isolation">2

看来我刚毕业的菜鸟还是不行啊,以后还是要多多学习,跟老鸟们好好学学,数据库知识相当重要,可是数据库知识我太欠缺了,以后要多学习一下数据库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值