首页 > 技术分享 > MySQL
收藏

MySQL select for...update,MySQL悲观锁的使用方法

10/30 09:31
大潇博客 原创文章,转载请标明出处

MySQL中的select...for update,也称为MySQL悲观锁,其作用是:

为了在查询数据时,避免其他用户对所查询的数据进行修改或删除等操作,造成表中数据的不一致性


例如:我们做抢购系统、限量兑换系统等,有限的数据被多人同时操作的情况下,容易造成相同数据被重复使用,严重影响结果的准确性,此时对数据上锁,即显得非常有必要


下面通过举例,简单介绍MySQL悲观锁的使用方法和效果


首先创建一张测试表:

CREATE TABLE test(

id int primary key auto_increment,

cid int NOT NULL,

name varchar(50) NOT NULL

);


添加测试数据:

INSERT INTO test(cid,name) VALUES(3,'北京'),(6,'上海'),(9,'深圳');


结果如下图所示:

创建测试表.png


下面再打开一个MySQL客户端,对锁进行测试

正常情况下, 我们使用select语句可以在不同客户端中,以相同条件随意查询,得到相同结果


比如上表中,查询id为2,cid为6的值,sql语句为:

SELECT * FROM test  WHERE id=2 AND cid=6;

假设这是在一个抢票系统中,这时有多人同时查到这条数据,就可能重复生成多个订单,导致数据错误。在这里使用悲观锁,可以很好的避免出现这种问题


使用悲观锁,首先要开启MySQL事务,禁止MySQL自动提交:

SET autocommit = 0;

然后开始事务:

begin;


查询对应数据:

select * from test where id = 2 and cid = 6 for update;


这时若两个乃至n个客户端同时操作,MySQL也会分先后。在得到结果的客户端,没有结束此次事务之前,后面的都需要排队等待,如下所示:

悲观锁测试.png


直到先查询到的执行“commit”或“rollback”结束本次事务,或者关闭本次连接结束事务,后面排队的再依次执行,如下图所示,右边的客户端查询等待了8秒:

悲观锁2.png


若只用MySQL悲观锁查询数据,和普通查询没什么区别,反而影响其它客户端的查询速度。而在查询到结果后,对数据进行修改、删除等操作,后面排队的再以相同条件进行查询时,即可避免查到重复结果,如图:

悲观锁3.png

如上图所示,使用select...for update锁定一条数据后,对其进行修改,另一个排队的客户端,再以相同条件查询,返回空结果。明确展示了悲观锁的效果


注意事项:

1、MySQL事务在MyISAM存储引擎下无效,故而悲观锁也不能使用。当发现select...for update无效时,请检查当前表的存储引擎,若为MyISAM,建议更换为InnoDB

2、事务的“commit”和“rollback”都可以对锁进行释放。在实际应用中要谨慎操作,考虑好各个因素后再上锁,并在合理位置对锁进行释放,避免陷入死锁


打赏

阅读排行

大家都在搜

博客维护不易,感谢你的肯定
扫码打赏,建议金额1-10元
  • 15601023311