mysql get lock_mysql中的get_lock锁机制解析

mysql中的get_lock锁机制解析

mysql> SELECT GET_LOCK('MySQL', 10) ; 返回结果为1,说明成功得到锁

+-----------------+

| ci_session_lock |

+-----------------+

| 1 |

+-----------------+

1 row in set (0.00 sec)

mysql>select RELEASE_LOCK('MySQL') ;

+----------------------------------------------------------+

| RELEASE_LOCK('MySQL') |

+----------------------------------------------------------+

| 1 |

+----------------------------------------------------------+

1 row in set (0.00 sec)

mysql> SELECT IS_USED_LOCK('MySQL') ; 返回结果为当前连接ID,表示名称为'MySQL'的锁正在被使用。

+-----------------+

| ci_session_lock |

+-----------------+

| 8 |

+-----------------+

1 row in set (0.00 sec)

mysql> SELECT IS_FREE_LOCK('MySQL') ; 返回结果为0,说明名称为'MySQL'的锁正在被使用。

+-----------------+

| ci_session_lock |

+-----------------+

| 0 |

+-----------------+

1 row in set (0.00 sec)

创建表:

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),再执行更新,这样所有的更新结果都是正确的。

优缺点分析

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

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

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

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

举个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’

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值