前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL事务与乐观锁

MySQL事务与乐观锁

作者头像
发布2019-11-26 18:52:27
1.4K0
发布2019-11-26 18:52:27
举报
文章被收录于专栏:WD学习记录

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://cloud.tencent.com/developer/article/1544299

最近感觉自己好像干了一件蠢事,写了一个事务包含A和B两个操作,然后又在A中加了乐观锁,导致失败率特别高。因此重新看了事务与乐观锁的资料。

一次封锁 两段锁

一次封锁法,就是方法的开始阶段,已经预先知道会用到哪些数据,然后全部锁住,在方法运行之后,再全部解锁。可以有效避免循环死锁。

两段锁协议

加锁阶段和解锁阶段。

加锁阶段:在任何数据进行读操作之前都有申请获得S锁,在进行写操作之前要申请并获得X锁,加锁不成功,则事务进入等待状态,直到加锁成功才继续。

解锁阶段:当事务释放了一个封锁之后,事务进入解锁阶段,在该阶段只能进行解锁操作而不能再加锁。

两段锁协议可以保证事务的并发调度串行化(串行化很重要,尤其是在数据恢复和备份的时候),但是无法避免死锁。

Update加行锁

如果update更新的where语句中的筛选条件没有索引,会导致MYSQL给整张表的所有数据加行锁。在SQL运行过程中,mysql并不知道哪些数据行是符合where条件的(没有索引)。如果一个条件无法通过索引快速过滤,存储引擎层面就会将所有记录加锁后返回,再由MYSQL层进行过滤。

但是实际使用过程中,mysql做了一些改进,在MYSQL过滤条件,发现不满足之后,会调用unlock_row方法,把不满足条件的纪录释放锁(违背了二段锁协议的约束)。这样做,保证了最后只会持有满足条件纪录上的锁。但是每条记录的加锁操作还是不能省略的。

这种情况同样适用于MYSQL的默认隔离级别可重复读。对一个数据量很大的表做批量修改的时候,如果无法使用相应的索引,MYSQL 过滤数据的时候特别慢,就会出现虽然没有修改某些行的数据,但是它们还是被锁住了。

快照读与当前读

快照读很可能读取的是历史数据,而不是数据库当前数据。

在MVCC中:

  • 快照读:就是select
    • select * from table ….;
  • 当前读:特殊的读操作,插入/更新/删除操作,属于当前读,处理的都是当前的数据,需要加锁。
    • select * from table where ? lock in share mode;
    • select * from table where ? for update;
    • insert;
    • update ;
    • delete;

Next-Key锁

行锁防止别的事务修改或删除,GAP锁防止别的事务新增,行锁和GAP锁结合形成的的Next-Key锁共同解决了RR级别在写数据时的幻读问题。

参考文档:

Innodb中的事务隔离级别和锁的关系

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/11/04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一次封锁 两段锁
  • Update加行锁
  • 快照读与当前读
  • Next-Key锁
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档