MySql FOR UPDATE 锁的一点问题……

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:

问题描述

假设一个情况,这里只是假设,真实的情况可能不会这样设计,但是假如真的发生了....
铁老大有一张这样的ticket表,用来存放北京到上海的票。

id
uid
start_addr
end_addr
book_time
1
1300009860
上海
北京
13866660321
2
0
上海
北京
3
0
上海
北京
4
0
上海
北京

uid 不等于0 并且 book_time 不等于0,则表示已售出,不许再更改。
年底了,大家开始抢了,当某一个人开始抢的时候,铁老大这样做了,当A开始抢的时候,从表中所有uid=0的记录中随机取出一条,然后修改当前记录的uid为A的uid,book_time为当前时间。
那么好了,这个时候并发产生了,10000个人同时抢最后剩下的10张票,有2个人A,B同时读取了uid=0 and id=2的记录,然后A把uid修改为自己的,book_time修改timeA,系统通知A抢票成功 紧接着,B同样修改了这条记录为自己的,那么这个时候A的票就失效了。
这里就考虑使用锁机制了,如果在A读取了这条记录后,并把这条记录加上写锁,那么别人就无法再读取加锁,也就不会修改多次了。

实验结果

实验了一下for update 加锁,然后发现了一些问题。
1、当我们使用主键查询去加锁的时候,可以对这条记录加行锁
打开一个终端:执行一下代码:

1
2
3
mysql>  begin ;
Query OK, 0  rows  affected (0.00 sec)
mysql>  select  from  ticket  where  id = 2  for  update ;

那么 id=2这个记录就会被加行写锁。
令一个终端将无法读取该记录,但是却可以读取其他记录

1
2
3
4
#可以读取加锁
mysql>  select  from  ticket  where  id = 3  for  update ;
#不可以读取
mysql>  select  from  ticket  where  id = 2  for  update ;

2、但是当我们按非主键查询会怎样呢

1
2
3
mysql>  begin ;
Query OK, 0  rows  affected (0.00 sec)
mysql>  select  from  ticket  where  uid = 0 limit 1  for  update ;

那么这个时候,这个表会被锁住,任何记录都不能再读取加锁

1
2
3
4
//不可读取,等待释放锁
mysql>  select  from  ticket  where  id = 1  for  update ;
//不可读取等待释放锁
mysql>  select  from  ticket  where  uid = 0 limit 1  for  update ;

但是表锁会减少并发。

结论

有没有一种方法,可以在非主键字段查询一条记录时上实现加行写锁,期待高手支招。























本文转自shayang8851CTO博客,原文链接:http://blog.51cto.com/janephp/1352679,如需转载请自行联系原作者

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
18天前
|
关系型数据库 MySQL 数据库
【MySQL实战笔记】 06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?-01
【4月更文挑战第17天】MySQL的锁分为全局锁、表级锁和行锁。全局锁用于全库备份,可能导致业务暂停或主从延迟。不加锁备份会导致逻辑不一致。推荐使用`FTWRL`而非`readonly=true`因后者可能影响其他逻辑且异常处理不同。表级锁如`lock tables`限制读写并限定操作对象,常用于并发控制。元数据锁(MDL)在访问表时自动加锁,确保读写正确性。
66 31
|
4天前
|
存储 关系型数据库 MySQL
MySQL的锁机制
MySQL的锁机制主要用于管理并发事务对数据的一致性和完整性的访问控制
21 4
|
9天前
|
存储 SQL 关系型数据库
|
13天前
|
关系型数据库 MySQL 数据库
MySQL锁解密:读锁与写锁
【4月更文挑战第20天】
23 1
|
13天前
|
关系型数据库 MySQL 数据库
|
13天前
|
算法 关系型数据库 MySQL
|
13天前
|
SQL 关系型数据库 MySQL
MySQL锁:解析隐式锁与显式锁
【4月更文挑战第20天】
36 0
|
13天前
|
关系型数据库 MySQL 数据库
|
13天前
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL 锁
16 1
|
19天前
|
关系型数据库 MySQL 索引
MySQL 锁机制
MySQL 锁机制
8 0