MySQL(innodb)锁总结
沉沙 2018-05-14 来源 : 阅读 1968 评论 0

摘要:MySQL(innodb)锁有两种:共享锁(s)和排他锁(x),本文对MySQL的两种所进行了详细的总结分析,希望对您有所帮助。

mysql(innodb)锁有两种:

共享锁(s):表示我正在读,你可以读(可以读表示加上s锁的读),但不能修改

排他锁(x):表示我正在修改,你不能读,也不能修改

单独的select语句(不去获得锁)可以执行,是因为读的是加锁或者事务前的快照版本

当然还有所谓的意向共享锁,意向排它锁,只是说上锁的数据由一行变成了多行,mysql中的锁可以看成java中的锁,在java里你只有获得了锁才能进入上锁的代码中,而mysql是你上锁后只有获得了锁才能进行相应的操作。

然后,innodb默认在修改语句上加了排它锁,也就是说

update t set a=1 where b=2

这样的语句其实真正是

select * from t where a =1 for update
update t set a=1 where b=2

共享锁

    共享锁是就像一起看一本书,我在看这一页,你也在看这一页,如果你想翻页什么的,就需要你和我都看完了这一页,不然肯定要打起来什么的了,当然,如果快看完的时候我表示想看上一页,你表示想看下一页,这要么就pk,要么就有一个人让步了,这就是死锁了,innodb默认解除死锁的方式是回滚较小的事务。

    例如 select * from t where a = 1 lock in share mode  ,后面的 lock in share mode  就是加上共享锁的意思了。共享的意思是分享,现在不是说是共享时代么,你想一下,共享单车之类的,每个人都可以用同一辆车,但是你如果想把这车变成自己的,我们就不同意了,这是公共的东西,也就是说你只能读,不能修改。就是说上锁后,其他其他人只能用,不能拿走或者改变它。

排他锁

    排他锁的话就是类似于租东西,在租期内这东西为我所有,你不能看,不能拿,不能改,瞅都不给你瞅一眼。你想要的话,只有等我还了这东西你才能拿得到。

    例如  select * from t where a = 1 for update, 后面的 for update 就是加上排他锁的意思,排他,我想这不用我多解释了。真正感觉起来,排他锁就类似于悲观锁,任何人不管做什么是都会妨碍到我,所以一点都不让动。当然,如果这样的情况,张三借了A书,李四借了B书,张三准备还书前是准备借B书的,而李四还书前准备借A书,但是一看书被借走了,就一直没有还书,在等着其他人还书好去借。这种情况又是典型的死锁了,这就需要书店居中协调了,总要有个人先还书,大不了一个人就当没借过这个书,不要你的钱,当然,书店肯定是不要那个更少的钱,这也就是innodb默认解死锁的方式,回退较小的事务。

其他扩展

   锁就是一个意向或者是状态,上锁后就是一个加锁的状态,而加上锁时就是一个意向。这些锁看起来并没有什么用,这就需要扩展了。当然这就牵扯到事务了

脏读

    脏数据:缓冲池中被修改的数据,还没有提交。(事务的操作时在缓冲池中,提交了才写到磁盘中)

    脏读:一个事务可以读到另一个事务未提交的数据。。。违背了事务的隔离性

    事务的隔离性:事务间隔离开来,不能互相干扰,每个事务都应该感受不到另一个事务

不可重复读

     不可重复读:一个事务读取同一记录两次但是数据不一样,即一个事务读取另一个事务提交的数据造成的结果,数据没有问题(数据已经写到磁盘),但是违反了事务的一致性。(与脏读区别为一个未提交(脏数据),一个已提交(有效数据))

    事务的一致性:事务开启时的状态应该和结束时的状态一致,如转账,能量守恒之类的。不可重复读,第一个事务的状态在第二个事务提交后已经改变。例如:a转账给b,但是中途另一个客户端把a转账给c了,状态已经改变(感觉也违反了隔离性)

虚读(幻读)

    虚读(幻读):一个事务更新了’全部数据‘,另一个事务插入了包含着’全部数据‘(一定条件的数据)里的数据,并提交,第一个事务这时候再提交,发现符合条件的数据并没有全部更新(跟不可重复读类似,只是虚读是删除和增加造成的,而不可重复读是修改造成的)

丢失更新

    丢失更新:比如一个转账的业务,a用客户端转给b二十元,这时我们的想法肯定是开启个事务,

    update a set balance=balance-20 ,

    update b set balance=balance+20 

    再提交了吧,如果因为网络延迟,第一个事务在提交前,a用另一个客户端给b转了30块钱,这时又开了另一个事务,

    update a set balance=balance-30 ,

    update b set balance=balance+30 

    本来应该减50的,我们的想法是叠加,但最后要么减了三十,要么减了20,这是一个严重的问题

明白了这三个,然后就是事务的隔离级别了,很明显,

read_uncommited 读未提交。。。这样肯定就是会脏读了。

read_commited 读已提交,这样脏读肯定就没了,但是造成了不可重复读。

repeatable_read 可重复读,这样不可重复读没了,但是虚读没有解决。

serializable 序列化,这样的话,一切都解决了。但是一般我们不用这种,因为这是强制每个数据行的操作时同步进行的,效率太低了,那么这问题就来了,我们不用这种隔离级别,怎么防止虚读和丢失更新呢,虚读还好一点,丢失更新的话可能丢失的就不是一点点数据了。

这时候锁的用处就来了,加上个排他锁,或者自己实现一个乐观锁,比如在数据库中加个version的字段,更新是判断一下,更新完后version加一。

锁算法

        record lock:单行记录锁

        gap lock : 范围锁,不包含记录本身

        next-key lock:锁定一个范围,并锁定记录本身

 

查看事务和锁的方法

information_schema 数据库 中 innodb_trx ,innodb_locks ,innodb_lock_waits表 可以查看相应的事务和锁情况

 

本文由职坐标整理发布,更多相关知识,请关注职坐标数据库MySQL频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程