关于Mysql的默认事务隔离级别 read repeatable

查询mysql的事务隔离级别 SELECT @@tx_isolation ;

一、数据库事务的隔离级别有4种: 

由低到高分别为:Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。

其中,mysql默认为 repeatable Read , 一个事务开始后,

1、如果针对一个字段的值 无论查询多少次,结果都是相同的,即使这个值已经被其它事务修改过。

2、如果是做统计,统计到的数据行数结果不会变,即使其它事务已经插入了新记录。

     所以 Repeatable Read 是有害的 ,如何避免呢?

顺便说一下相关的几个概念:

1. 脏读 :其它事务还没提交就被另当前事务读取到了,理解:脏就是不想要的,不是真正需要的。坏事。

2. 不可重复读 :当前事务两次读到的数据不一致,因为其它事务也在修改并提交,我认为这不是坏事,因为数据是真实的。repeatable read级别的隔离是不存在的,read commited 中存在,看上去这是好事啊。

3. 幻读 : 简单理解是当前事务两次查询发现数据不一致,结果是由于其它事务插入了数据(已经提交)导致的。  幻读可以理解为海市蜃楼(光的折射),感觉像幻像实际是都是真实的信息。 好事。

 

二、如何避免Repeatable Read 导致的问题:

1、关于修改某字段的值时,一定要使用乐观锁或者悲观锁。

     例如更新账户金额:   update  order_info o set o.money=money-10  

    而不应该先查询money 计算完成后再进行更新

               money = money -10 ;  --- 这里money可能早被其它事务改了

               update  order_info o set o.money= :money

 

三、验证事务Mysql的事务隔离级别

建好表,打开两个mysql命令行窗口,插入一条记录  age=1 ,然后通过两个并发事务对age分别加1,预期接结果为  3 

1)两个窗口分别开始事务

start TRANSACTION ;

2)窗口一更新表

update user_info set age = age+1 where id=1;

3)窗口二更新 表

update user_info set age = age+1 where id=1

此时发现窗口二卡住了,实际上如果sql中没有在where条件中使用索引的话,不论更新哪个字段都会被卡住。为什么?

因为在采用INNODB的MySQL中,更新操作默认会加行级锁.所以窗口二这里会卡住。

行级锁是基于索引的。如果没有使用索引则会锁表,如果操作用到了主键索引会先在主键索引上加锁,然后在其他索引上加锁,否则加锁顺序相反。在并发度高的应用中,批量更新一定要带上记录的主键,优先获取主键上的锁,这样可以减少死锁的发生。

4)窗口一 提交事务

commit;  

此时数据库中的age值为2

 

5)窗口二 恢复后,

查询age:

select age from user_info 发现 age结果还是为 1 (这是因为repeatable read 隔离级别导致)

再次执行 更新

update user_info set age = age+1;

然后进行查询 

select age from user_info 发现 ,查询结果是正确:3 而不是错误的 2

6) 窗口二 commit ;

打开数据库查看,结果为 3

 

参看文章:http://ju.outofmemory.cn/entry/199937

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值