mysql 悲观锁 详细讲解_mysql 悲观锁详解
悲观锁指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
以MySQL InnoDB为例:
商品goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么对某个商品下单时必须确保该商品status为1。假设商品的id为1。
1 不采用锁:
(1) 查询出商品信息select status fromgoods where id=1;复制代码
(2) status如果为1则根据商品信息生成订单insert into orders (goods_id) values (1);复制代码
(3) 修改商品status为2update goods set status=2;复制代码
第一步操作中,查询出来的商品status为1。但是当我们执行第三步Update操作的时候,在高并发情况下有可能出现其他人先一步对商品下单把goods中id为1的 status修改为2了,但是我们并不知道数据已经被修改了,这样就可能造成同一个商品被下单2次。
2 使用悲观锁:
上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。
注:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
可以使用命令设置MySQL为非autocommit模式:set autocommit=0;复制代码
然后就可以执行正常业务了。具体如下:
开始事务begin;/begin work;/start transaction; (三者选一就可以)复制代码
查询出商品信息select status from goods where id=1 for update;复制代码
根据商品信息生成订单insert into t_orders (goods_id) values (1);复制代码
修改商品status为2update goods set status=2;复制代码
提交事务commit;/commit work;(任选一)复制代码
与普通查询不一样的是,使用了select…for update的方式,这样就通过数据库实现了悲观锁。此时在goods表中,id为1的 那条数据就被锁定了,其它的事务必须等本次事务提交之后才能执行。这样就可以保证当前的数据不会被其它事务修改。
注:在事务中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一笔数据时会等待其它事务结束后才执行,一般SELECT ... 则不受此影响。拿上面的实例来说,当执行select status from goods where id=1 for update后,另外的事务中如果再次执行select status from t_goods where id=1 for update,则会一直等待第一个事务的提交,此时第二个查询处于阻塞的状态,但是如果在第二个事务中执行select status from t_goods where id=1;则能正常查询出数据,不会受第一个事务的影响。
MySQL select…for update的Row Lock与Table Lock
上面提到,使用select…for update会把数据给锁住,需要注意一些锁的级别,MySQL InnoDB默认Row-Level Lock,所以只有「明确」地指定主键,MySQL 才会执行Row lock (只锁住被选取的数据) ,否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。
以下例子中数据库表goods,包括id,status,name三个字段,id为主键,为测试数据库锁,使用两个console来模拟不同的事务操作,分别用console1、console2来表示。
例1:明确指定主键,并且有此数据,row lock
console1:MySQL [ning]> begin;
Query OK, 0 rows affected (0.00 sec)
MySQL [ning]> select * from goods where id=1 for update;
+----+--------+------+
| id | status | name |
+----+--------+------+
| 1 | 1 | T恤 |
+----+--------+------+
1 row in set (0.00 sec)复制代码
console2(查询被阻塞):MySQL [ning]> begin;
Query OK, 0 rows affected (0.00 sec)
MySQL [ning]> select * from goods where id=1 for update;复制代码
如果console1长时间未提交,console2则会报错:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction复制代码
例2:明确指定主键,若查无此数据,无lock
console1:MySQL [ning]> select * from goods where id=3 for update;
Empty set (0.00 sec)复制代码
console2:MySQL [ning]> select * from goods where id=3 for update;
Empty set (0.00 sec)复制代码
查询结果为空,查询无阻塞,说明console1没有对数据执行锁定
例3: 无主键,table lock
console1:MySQL [ning]> select * from goods where name="T恤" for update;
+----+--------+------+
| id | status | name |
+----+--------+------+
| 1 | 1 | T恤 |
+----+--------+------+
1 row in set (0.00 sec)复制代码
console2:MySQL [ning]> select * from goods where name="衬衫" for update;复制代码
查询阻塞,说明console1把表给锁住了
例4: 主键不明确,table lock
console1:MySQL [ning]> select * from goods where id>0 for update;
+----+--------+--------+
| id | status | name |
+----+--------+--------+
| 1 | 1 | T恤 |
| 2 | 1 | 衬衫 |
+----+--------+--------+
2 rows in set (0.01 sec)复制代码
console2:MySQL [ning]> select * from goods where id>0 for update;复制代码
查询被阻塞,说明console1把表给锁住了
例5: 主键不明确,table lock
console1:MySQL [ning]> select * from goods where id<>1 for update;
+----+--------+--------+
| id | status | name |
+----+--------+--------+
| 2 | 1 | 衬衫 |
+----+--------+--------+
1 row in set (0.00 sec)复制代码
console2:MySQL [ning]> select * from goods where id<>2 for update;复制代码
console2:查询被阻塞,说明console1把表给锁住了
以上是关于数据库主键对MySQL锁级别的影响实例,除了主键外,使用索引也会影响数据库的锁定级别,明确指定索引且有数据则是row lock,明确指定索引且查无此数据则无lock
mysql 悲观锁 详细讲解_mysql 悲观锁详解相关推荐
- mysql如何查看事务日记_MySQL日志查看详解
解决问题: 了解MySQL日志? 怎样查看错误日志? 怎样查看慢日志? 1. MySQL日志分类? MySQL日志主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志. 1.1 错误日志: ...
- mysql单表查询实例_MySQL简单查询详解-单表查询
MySQL简单查询详解-单表查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询的执行路径 一条SQL查询语句的执行过程大致如下图所示: 1>.客户端和服务端通过my ...
- mysql存储引擎简书_MySQL存储引擎详解
一,基础 1,插件式存储引擎,允许第三方组织,根据其api来设计,很多功能需要依赖引擎支持,比如事务 2, 5.5以后默认为innodb,之前为myISAM,innodb支持事务,myISAM不支持 ...
- mysql 储存过程放到哪_MySQL储存过程详解
我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的 ...
- MySql数据库explain用法示例_mysql explain用法详解
explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了,如: explai ...
- mysql 大量数据 更改索引_Mysql索引数据结构详解与索引优化
本篇文章主要学习了MySQL的索引的数据结构的认识,做一个大概的了解即可. 一.索引 在关系数据库中,索引是一种单独的.物理的对数据库表中一列或多列的值进行排序的一种存储数据结构,它是某个表中一列或若 ...
- MySQL 变量的详细讲解
MySQL 变量的详细讲解 每博一文案 见面少没关系,你不要喜欢上别人就好 一禅小和尚的微博视频 很喜欢席慕容写的一句话,挫折回来,也会去,热泪会流下,也会收起,没有什么 可以让我气馁的,因为我有着长 ...
- mysql 外键详解_mysql外键详解
1.1.MySQL中"键"和"索引"的定义相同,所以外键和主键一样也是索引的一种.不同的是MySQL会自动为所有表的主键进行索引,但是外键字段必须由用户进行明确 ...
- [Python从零到壹] 八.数据库之MySQL和Sqlite基础知识及操作万字详解
欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...
- Mysql配置文件my.cnf配置及配置参数详解
Mysql配置文件my.cnf 安装了mysql没有my.cnf文件的情况 1.可以把mysql的示例配置文件,如my-medium.cnf拷贝到/etc/my.cnf,再去修改/etc/my.cnf ...
最新文章
- shell 脚本实战笔记(9)--linux自动批量添加用户
- 循环查询sql带逗号(,)分隔的数据 以及一对多数据转化为逗号(,)分割数据...
- elasticSearch 安装和 head插件使用
- (1).数据结构概述
- 关闭word_记一次毕设消失事件始末,及mac+word文档消失恢复方法汇总
- sqlalchemy create engine
- jnativecpp.dll一定要放到系统目录下吗_「实用」室内甲醛到底该如何去除?关键要做到这两点...
- linux rz上传文件及出错解决方案
- 山东大学暑期实训——智能人物画像综合分析系统
- linux-网络安全防火墙
- python 与 selenium
- C++typedef的用法
- C++语法——详解智能指针的概念、实现原理、缺陷
- 仅改变rowspan背景_重排96黄金一代选秀前4位!艾弗森仅第三,前两名竟然还是队友...
- 增量更新对开发者有何影响?
- 新媒体背景下大学生的志愿服务参与研究(lunwen+任务书)
- 双卡手机发送短信 - 坑爹的双卡双待
- [Rtsp]海康网络摄像头基于RTSP协议的windows平台监控
- 【汽车ECU开发】------INCA使用教程
- 人工神经网络原理及应用,人工神经网络详解图
热门文章
- python网络编程原理_图解Python网络编程
- 纯互联网项目“失宠”乐博资本杨宁称今后只投O2O
- linux oel7没有网络,sudo su命令不在OEL 7中工作(sudo su command not working in OEL 7)
- 在arm64上基于qemu的vhost user blk设备hotplug
- 网络SSID是什么意思
- 单片机学习(三)8位数码管显示8个字符的程序及详解
- 怎么制作你的第一个机器人
- codecademy 命令行手册(中英文)
- SEO系列之站内优化
- 前端js正则表达式2