您的位置:首页 > 数据库 > MySQL

mysql中的get_lock锁机制解析

2016-06-30 18:43 1661 查看
1. 先来看一看语法

select get_lock(key, timeout) from dual;
select release_lock(key) from dual;


2. 概述

(1)get_lock会按照key来加锁,别的客户端再以同样的key加锁时就加不了了,处于等待状态。

(2)当调用release_lock来释放上面加的锁或客户端断线了,上面的锁才会释放,其它的客户端才能进来。

3. 举例说明

以下定义两个客户端,A1和A2。

创建表:

create table test_lock(
id int,
name varchar(50),
address varchar(50)
);
insert into test_lock values(1,'tt','aaaaaaaaaaaaaaaaaaaa');


A1:

select get_lock('key_lock', 100);

update test_lock set name = 'tt2', address = 'aaaaaaaaaaaaaaaaaaaa' where id = 1; #只更新name列

select release_lock('key_lock');


A2:

select get_lock('key_lock', 100);

update test_lock set name = 'tt', address = 'bbbbbbbbbbbbbbbbbbbbbbb' where id = 1;  #只更新address列

select release_lock('key_lock');


执行A1的第一条语句后执行A2的第一条语句会发现一直卡在那里,直接执行了A1的最后一条语句(或过期或断线)为止才能继续执行A2的语句。

如果按上面的顺序分别执行了A1和A2中的语句,则最后表中的数据是按A2的第二语句更新那样的显示,这种结果当然不是我们想要的,实际项目中,应该是先查出来id为1的数据,把某列更新的值set进去(针对Java),再执行更新,这样所有的更新结果都是正确的。

4. 优缺点分析

(1)这种方式对于更新所有列比较有效,但是得把查询的语句也放在锁内执行;

(2)这种方式当客户端无故断线了会自动释放锁,比较好,不像redis锁那样,如果加完锁断了,那么锁一直在;

(3)这种方式是针对锁内的所有操作加锁,并不针对特定表或特定行,所以使用了同一个Key的锁但不同的操作都会共用一把锁,会导致效率低下;

(4)如果查询语句放在锁之前,则数据可能是旧的,更新之后会把查询之后更新之前别的客户端更新的数据覆盖掉;

5. 举个Java例子的伪代码

A1客户端:

execute("select get_lock('key_lock', 100)");
User user = queryUser(1);
user.setName("tt1");
updateUser(user);
execute("select release_lock('key_lock')");


A2客户端:

execute("select get_lock('key_lock', 100)");
User user = queryUser(1);
user.setAddress("bbbbbbbbbbbbbb");
updateUser(user);
execute("select release_lock('key_lock')");


按照以上这种方式操作则两条更新语句都是正确的,最后的结果应该是

name = ‘tt1’,

address = ‘bbbbbbbbbbbbbb’
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql