悲观锁指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

以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 悲观锁详解相关推荐

  1. mysql如何查看事务日记_MySQL日志查看详解

    解决问题: 了解MySQL日志? 怎样查看错误日志? 怎样查看慢日志? 1. MySQL日志分类? MySQL日志主要包含:错误日志.查询日志.慢查询日志.事务日志.二进制日志. 1.1 错误日志: ...

  2. mysql单表查询实例_MySQL简单查询详解-单表查询

    MySQL简单查询详解-单表查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询的执行路径 一条SQL查询语句的执行过程大致如下图所示: 1>.客户端和服务端通过my ...

  3. mysql存储引擎简书_MySQL存储引擎详解

    一,基础 1,插件式存储引擎,允许第三方组织,根据其api来设计,很多功能需要依赖引擎支持,比如事务 2, 5.5以后默认为innodb,之前为myISAM,innodb支持事务,myISAM不支持 ...

  4. mysql 储存过程放到哪_MySQL储存过程详解

    我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的 ...

  5. MySql数据库explain用法示例_mysql explain用法详解

    explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了,如: explai ...

  6. mysql 大量数据 更改索引_Mysql索引数据结构详解与索引优化

    本篇文章主要学习了MySQL的索引的数据结构的认识,做一个大概的了解即可. 一.索引 在关系数据库中,索引是一种单独的.物理的对数据库表中一列或多列的值进行排序的一种存储数据结构,它是某个表中一列或若 ...

  7. MySQL 变量的详细讲解

    MySQL 变量的详细讲解 每博一文案 见面少没关系,你不要喜欢上别人就好 一禅小和尚的微博视频 很喜欢席慕容写的一句话,挫折回来,也会去,热泪会流下,也会收起,没有什么 可以让我气馁的,因为我有着长 ...

  8. mysql 外键详解_mysql外键详解

    1.1.MySQL中"键"和"索引"的定义相同,所以外键和主键一样也是索引的一种.不同的是MySQL会自动为所有表的主键进行索引,但是外键字段必须由用户进行明确 ...

  9. [Python从零到壹] 八.数据库之MySQL和Sqlite基础知识及操作万字详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  10. Mysql配置文件my.cnf配置及配置参数详解

    Mysql配置文件my.cnf 安装了mysql没有my.cnf文件的情况 1.可以把mysql的示例配置文件,如my-medium.cnf拷贝到/etc/my.cnf,再去修改/etc/my.cnf ...

最新文章

  1. shell 脚本实战笔记(9)--linux自动批量添加用户
  2. 循环查询sql带逗号(,)分隔的数据 以及一对多数据转化为逗号(,)分割数据...
  3. elasticSearch 安装和 head插件使用
  4. (1).数据结构概述
  5. 关闭word_记一次毕设消失事件始末,及mac+word文档消失恢复方法汇总
  6. sqlalchemy create engine
  7. jnativecpp.dll一定要放到系统目录下吗_「实用」室内甲醛到底该如何去除?关键要做到这两点...
  8. linux rz上传文件及出错解决方案
  9. 山东大学暑期实训——智能人物画像综合分析系统
  10. linux-网络安全防火墙
  11. python 与 selenium
  12. C++typedef的用法
  13. C++语法——详解智能指针的概念、实现原理、缺陷
  14. 仅改变rowspan背景_重排96黄金一代选秀前4位!艾弗森仅第三,前两名竟然还是队友...
  15. 增量更新对开发者有何影响?
  16. 新媒体背景下大学生的志愿服务参与研究(lunwen+任务书)
  17. 双卡手机发送短信 - 坑爹的双卡双待
  18. [Rtsp]海康网络摄像头基于RTSP协议的windows平台监控
  19. 【汽车ECU开发】------INCA使用教程
  20. 人工神经网络原理及应用,人工神经网络详解图

热门文章

  1. python网络编程原理_图解Python网络编程
  2. 纯互联网项目“失宠”乐博资本杨宁称今后只投O2O
  3. linux oel7没有网络,sudo su命令不在OEL 7中工作(sudo su command not working in OEL 7)
  4. 在arm64上基于qemu的vhost user blk设备hotplug
  5. 网络SSID是什么意思
  6. 单片机学习(三)8位数码管显示8个字符的程序及详解
  7. 怎么制作你的第一个机器人
  8. codecademy 命令行手册(中英文)
  9. SEO系列之站内优化
  10. 前端js正则表达式2