如何解决幻读_事务隔离:幻读到底是什么?

数据库事务要满足ACID:

  • Atomicity原子性
  • consistency一致性
  • isolation隔离性
  • durability持久性

事务的隔离级别:

  • 读未提交
    • 出现问题:脏读
  • 读提交
    • 问题:不可重复读
  • 可重复读
    • 问题:幻读
  • 串行化

MySQL默认隔离级别是可重复读,而Oracle的默认隔离级别是读提交

1.1. MySQL是如何保证可重复读的?

确切的说是InnoDB,如何实现可重复读事务的。

MVCC(数据库多版本并发控制),通过多个版本号来控制。

也就是说每一个修改都会对应多个回滚版本号。

01bb7d830baa72004ab2855d6046a009.png

通过版本号来控制这一时刻下,类似于静态数据。(todo这里后面有讲到是使用什么来做到版本控制的)

MySQL不可能将所有的版本日志都记录下来,这样实在太浪费空间了。

那么MySQL什么时候删除日志?

在不需要的时候删除,MySQL会自行判断,当没有事务用到此回滚日志时,就会删除。

由此便引出一个主意点:

  • 避免长事务
  • 如何避免长事务?
    • 很多时候长事务,其实是隐形发生的,并不是估计为之,误用导致。
    • 开启事务的方式
      • 显示启动事务语句,begin或者start transaction。需要显示的commit,回滚rollback。
      • set autocommit=0,自动提交会被关掉。只要执行一个select语句就会开启一个事务,并且不会自动commit,事务会一直存在,直到手动commit或者rollback语句,或者断开连接。

有些客户端会在连接成功时,自动设置set autocommit=0,会导致接下来的查询都在一个长事务当中。

建议使用方式:

  1. 总是设置set autocommit=1显示语句开启事务,必须使用begin与commit或者rollback语句对来处理事务。
  2. 如果频繁使用事务,可以使用commnit work and chain语法,在一个事务commit之后,会自动开启下一个事务。
  3. 监控information_schema.innodb_trx表,发现长事务就要立刻警报select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60

1.2. 注意:MySQL默认可重复读但是还是会出现幻读

1.2.1. 什么是幻读?

这篇文章讲的很透彻

也是可重复读的特性导致。

b44b236f240e5ec5dd55147ca499d41e.png

1.2.2. 如何解决幻读?

  • select * from test for update
    • 行级排他锁
  • select * from test lock in share mode
    • 行级共享锁
    • 注意可能会发生死锁

1.2.2.1. select for update

656694cafa31e7fcce693bc432dceed4.png

1.2.2.2. Select lock in share mode

ae90513036f34605cf55f5ac9c11bde3.png
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值