mysql innodb锁_MySQL(innodb)锁总结

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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值