一点PHP博客分享关于在编程中最常用的几种锁机制,分别是排它锁、共享锁、悲观锁、乐观锁,本文深度详细分析解释各锁的使用场景以及实现方式和它们之间的区别。本文内容由博主自身理解以及查阅相关资料后的总结,有不对的地方请及时纠正。
1.排它锁
客户端1
1
2
3
4
5
6
7
setautocommit=0;
BEGIN;
SELECT *frombb_blogwhereid=1forupdate;
updatebb_blogsettitle=5525whereid=1;
//这里没有提交事务 commit,因为提交之后就是解锁了
客户端1
1
SELECT *frombb_blogwhereid=1forupdate;
//不能看到数据,这里会被堵塞,甚至不能修改同样堵塞。
1
SELECT *frombb_blogwhereid=1;
//可以看到数据,但是不能修改。
2.共享锁
客户端1
1
2
3
4
5
6
7
setautocommit=0;
BEGIN;
SELECT *frombb_blogwhereid=1lockinsharemode;
updatebb_blogsettitle=5525whereid=1;//如果不使用
//这里没有提交事务 commit,因为提交之后就是解锁了
客户端2
1
SELECT *frombb_blogwhereid=1lockinsharemode;
//如果没有出现update修改操作,可以共享看到数据但是不能修改修改操作会被堵塞,如果客户端1使用了update操作,这里将会堵塞不能看到数据。
1
SELECT *frombb_blogwhereid=1lock;
//无论客户端1是否使用了update操作都可以共享看到数据(客户端1没update之前的老数据 而不是update之后的数据)。但是不能修改 修改操作会被堵塞。
总结:只要客户端1上了共享锁 客户端2无论是否使用 lock in share mode;都可以看到数据,但是不能操作。如果客户端1做了update操作,客户端2使用了lock in share mode;不能看到数据不能操作,直接select可以看到之前的老数据。
3.乐观锁
表示在查询数据表某一行记录时,很乐观的认为其他人不会在这个时候对这行数据进行update操作,只有在update的时候才会上锁认为别人也在操作这条数据。
乐观锁常实现方式通过version,在数据表中加一个字段version,需要操作数据的时候 先将他和其他数据一起取出,然后在update的时候where中加入version这个字段,并且修改的时候+1。如果这个字段被人改过了,就认为这条数据已经被人操作了。
4.悲观锁
表示无论在查询数据或者修改数据的时候都认为同时有人在修改数据,保证在查询的时候也只能是一个人在操作,一般是使用mysql本身的排它锁+事物的方式现实,
1
2
3
4
5
6
7
setautocommit=0;
BEGIN;
SELECT *frombb_blogwhereid=1forupdate;//排它锁的方式
updatebb_blogsettitle=5525whereid=1;
这个时候 只能我在进行数据操作,其他人访问这条数据都是堵塞状态。
5.mysql innodb的行锁机制
如果字段上有主键索引,在使用update操作该数据的时候才会触发行锁机制,其他update的操作都会被堵塞,如果没有主键索引字段则会直接进行表锁。
悲观锁和乐观锁区别(需要结合其他自行实现):
悲观锁基本依靠数据库排它锁或者其他锁实现/或者redis等其他,乐观锁通过代码+字段实现。
悲观锁,无论是读还是写,都要上锁 通过for update。事物没有提交之前 只能有一个人能访问该数据。
乐观锁,数据只要没有出现update的操作,大家都可以访问该数据。
共享锁和排它锁区别总结(数据库自带锁):
使用了排它锁,就算是select读取操作同样会被堵塞。
使用了共享锁 读取操作可以进行,前提是上锁者没有进行update操作