文章详情

短信预约信息系统项目管理师 报名、考试、查分时间动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

理解共享锁和排它锁

2014-06-24 05:01

关注

理解共享锁和排它锁

1.2 例子:

共享锁事务读取

以不同的 session 来举例:

a:

start transaction;    
select * from demo where id = 1 lock in share mode;

b:

start transaction;    
select * from demo where id = 1 lock in share mode;

此时 a 和 b 都可以正常获取结果,那么再加入 c 排他锁读取尝试

c:

start transaction;    
select * from demo where id = 1 for update;

在 c 中则无法获取数据,直到超时或其它事物 commit

共享锁事务更新

a:

update demo set name = "xxx" where id = 1;

可以很快获取执行结果。当 b 再次执行修改 id=1 的语句时:
b:

update demo set name = "yyy" where id = 1;

就会出现死锁或者锁超时,错误如下:

Deadlock found when trying to get lock; try restarting transaction

或者:

Lock wait timeout exceeded; try restarting transaction

必须等到 a 完成 commit 动作后,b 才会正常执行,如果此时多个 session 并发执行,可想而知出现死锁的几率将会大增。

c 则更不可能

1.3应用场景

拿mysql官方文档的例子来说,一个表是child表,一个是parent表,假设child表的某一列child_id映射到parent表的c_child_id列,那么从业务角度讲,此时我直接insert一条child_id=100记录到child表是存在风险的,因为刚insert的时候可能在parent表里删除了这条c_child_id=100的记录,那么业务数据就存在不一致的风险。

正确的方法是再插入时执行select * from parent where c_child_id=100 lock in share mode,锁定了parent表的这条记录,然后执行insert into child(child_id) values (100)就ok了。

1.4 小结

共享锁,事务加多少,都能读。修改是唯一的,必须等待前一个事务 commit,才可以下个修改

2.排它锁

2.1 概念

当一个事物加入排他锁后,不允许其他事务加共享锁或者排它锁读取,更加不允许其他事务修改加锁的行。

2.2 例子

排他锁不同事务之间的读取

同样以不同的 session 来举例

a:

start transaction;
select * from demo where id = 1 for update;

b:

start transaction;
select * from demo where id = 1 for update;

当 a 执行完成后,再次执行 b,此时 b 也会卡住,无法立刻获取查询的数据。直到出现超时

Lock wait timeout exceeded; try restarting transaction

或 a commit 才会执行

那么再使用 c 加入共享锁尝试

select * from demo where id = 1 lock in share mode;

结果也是如此,和 b 一样,超时或等待 a commit

Lock wait timeout exceeded; try restarting transaction

排他锁事务之间的修改

当在 a 中执行 update 语句:

update demo set name ="xxx"  where id = 1;

可以正常获取结果,接着在 b 中执行修改

update demo set name = "yyy" where id = 1;

则会卡住直接超时或 a commit, 才会正常吐出结果

c 也很明显和 b 一样的结果,这里就不多赘述

2.3应用场景

如果是同一张表的应用场景,举个例子,电商系统中计算一种商品的剩余数量,在产生订单之前需要确认商品数量>=1,产生订单之后应该将商品数量减1。

1 select amount from product where product_name="XX";  
2 update product set amount=amount-1 where product_name="XX";  

显然1的做法是是有问题,因为如果1查询出amount为1,但是这时正好其他session也买了该商品并产生了订单,那么amount就变成了0,那么这时第二步再执行就有问题。使用排它锁就可以避免这种问题:

select * from demo for update

2.4 小结

不允许其它事务增加共享或排他锁读取。修改是唯一的,必须等待前一个事务 commit,才可以下一个修改

最后

lock in share mode适用于两张表存在业务关系时的一致性要求,for  update适用于操作同一张表时的一致性要求。

— —感谢浏览♥

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯