说说mysql的锁

       mysql提供了两种锁,一种使用select for update,一种mysql函数get_lock(str,timeout)。下面是我对其使用和一些肤浅的领悟:

       首先是select for update,特别说明,mysql现在依旧不支持 select for update no wait。。。

      测试环境如下:

==========================

数据库版本:

======================================

表结构(word_mood)



 

============================================================================================================================================

引擎:

 
 下面开始介绍其使用和应该注意事项:

大家请注意查看上图显示的引擎是innodb为默认,故我要测试使用的也就是InnoDB。从我勾选出来的可以看出,它支持事物,行级锁,外键。什么是行级锁,我想大家应该都很明白,我们

再通过一些例子来加深影响。首先我会开两个console来演示:

 

 

=================================

 



 

A客户端对message_id=5的数据进行select for update操作,B客户端也对message_id=5的进行select for update操作,大家应该都已经猜到了结果,我们还是来验证下是否正确。

 



 

========================================================

 



 大家请看上面的结果集,A客户端显示出message_id=5的结果,而B客户端在等待一段时间出现获取锁超时。说明for update具有锁表的功能,A客户端一直持有锁,并没有释放(事务没有提交),故B客户端在一定时间没有获取到锁则抛出了timeout异常。那么我们继续研究,此时是锁表还是锁行。

我会对message_id=1的数据for update。若是锁表此时,应该继续超时,若是锁行,则会显示出结果。大家请看下面:



 大家请看,此时我们查询出message_id=1的结果,说明当where条件是主键的时候for update是进行锁行的,那么当where条件不存在主键是锁表还是锁行呢。

我们继续来验证,此时我会对A客户端message_content=0的数据进行for update,B客户端message_content=1的数据for update。在这之前,我会把这两个客户端的事务commit,然后重新开启事务



 

========================================================================



 

 

大家看上图,发现客户端B结果是empty set,说明A客户端执行的for update锁住word_mood这张表了。这也说明了当我们执行for update的时候若where条件是表的主键那么将只是锁住查询的那一行的数据,而不存在主键则是锁住整张表。那么又有同学会问,既然for update是锁行,能否对其他行进行操作呢?我将通过下面的试验展示给大家,在这之前我会commit掉A,B客户端,重新开启事务.

 



 

====================================================================



 

在上面的例子中我对A客户端的message_id=0数据进行了for update操作,然后在B客户端对message_id=5的数据进行了update,然后在insert了一条数据,均成功。说明我们锁住的只是当前行的update操作,而对其行没有影响。

 

现在我们再来看看get_lock(str,timeout)这个函数,这是mysql提供的,我们可以在开发中利用这个函数来堵塞线程。使用起来简单,但是坑也还是有的,只要明白了这个坑我们就可以在开发中避免。

我们先来说说这个函数的两个参数。第一个参数代表是要锁的字符串,第二个参数代表的是获取锁等待的时间。当返回值是1代表成功,0没有获取到值,null代表超时现在我就来演示如何使用,此时我会开两个console



 

=====================================

在上图中我首先用A客户端获取了一个lock锁,然后B客户端再去获取的时候,返回值为0。

既然有获取那么就有释放,函数release_lock(str)。参数代表要释放的锁;返回值:1成功,0,失败。

 

在下面的试验中,我会在A客户端释放锁(lock),B客户端继续获取锁



 

====================

 我们发现当A释放掉时,B才能获取到锁。这是正常释放和获取锁的方式。既然有正常那就有异常了,在此我希望大家能记住这个异常。。。因为在开发中我们一定要避免这个异常,否则会出现不可控的情况。下面我们就来试验下这个异常。



 

 

大家请看上图,我首先获取了一个lockA这个锁,然后使用is_free_lock函数(返回1-空闲;0-正在使用)查看锁的使用情况,发现正在使用,结果正常。然后在获取锁lockB,然后使用is_free_lock函数再次查看lockA的使用情况,发现其使用状态变成了空闲。而lockB处于正在使用。并没有出现lockA,lockB都处于正在使用状态,大家可以理解为,当我们再次lock一个新的字符串的时候,mysql就会把以前存在的锁释放掉,然后再获取当前这个新的锁。所以我们在开发的时候尽量使用常量并且必须调用release释放锁

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值