今天看代码看到有select name from user where id = 1 for update,有点懵逼,完全没有见过,只能说自己见识少了,那就只能学习一下。先做一下基本知识了解(大部分都是整理了别人的文档,如有侵权还请告知):

锁的基本概念
  当多事务争取一个资源时,有可能导致数据不一致,这个时候需要一种机制限制,并且将数据访问顺序化,用来保证数据库数据的一致性,锁就是其中的一种机制。我们可以用商场的试衣间来做个比喻,商场里得每个试衣间都可供多个消费者使用,因此可能出现多个消费者同时试衣服需要使用试衣间,这时候就产生冲突了,为了避免冲突,试衣间装了锁(其实就是进去之后把门拴住),某一个试衣服的人在试衣间里把锁锁住了,其他顾客就不能再从外面打开了,只能等待里面的顾客,试完衣服,从里面把锁打开,外面的人才能进去(网上找到的比喻,非常形象)。不过我想要是并发了就尴尬了,哈哈。

锁的基本类型
  数据库上的操作可以归纳为两种:读和写。
  多个事务同时读取一个对象的时候,是不会有冲突的。同时读和写,或者同时写才会产生冲突。因此为了提高数据库的并发性能,通常会定义两种锁:共享锁和排它锁。

共享锁(Shared Lock,也叫S锁)
  共享锁(S)表示对数据进行读操作。因此多个事务可以同时为一个对象加共享锁。(如果试衣间的门还没被锁上,顾客都能够同时进去参观)
  产生共享锁的sql:select * from ad_plan lock in share mode;

共享锁的使用场景
  SELECT ... LOCK IN SHARE MODE走的是IS锁(意向共享锁),即在符合条件的rows上都加了共享锁,这样的话,其他人可以读取这些记录,也可以继续添加IS锁,但是无法修改这些记录直到你这个加锁的过程执行完成(完成的情况有:事务的提交,事务的回滚,否则直接锁等待超时)。
  SELECT ... LOCK IN SHARE MODE的应用场景适合于两张表存在关系时的写操作,拿mysql官方文档的例子来说,一个表是child表,一个是parent表,假设child表的某一列child_id映射到parent表的c_child_id列,那么从业务角度讲,此时我直接insert一条child_id=100记录到child表是存在风险的,因为刚insert的时候可能在parent表里删除了这条c_child_id=100的记录,那么业务数据就存在不一致的风险。正确的方法是再插入时执行select * from parent where c_child_id=100 lock in share mode,锁定了parent表的这条记录,然后执行insert into child(child_id) values (100)就不会存在这种问题了。

排他锁(Exclusive Lock,也叫X锁)

  排他锁也叫写锁(X)。

  排他锁表示对数据进行写操作。如果一个事务对对象加了排他锁,其他事务就不能再给它加任何锁了。(某个顾客把试衣间从里面反锁了,其他顾客想要使用这个试衣间,就只有等待锁从里面给打开了)
产生排他锁的sql: select * from ad_plan for update;看到了吧,for update出现了,所以for update 是排他锁,涨知识了。
排他锁的使用场景:

  使用场景一:订单的商品数量
 
   但是如果是同一张表的应用场景,举个例子,电商系统中计算一种商品的剩余数量,在产生订单之前需要确认商品数量>=1,产生订单之后应该将商品数量减1。
    1 select amount from product where product_name='XX';
    2 update product set amount=amount-1 where product_name='XX';

    显然1的做法是是有问题,因为如果1查询出amount为1,但是这时正好其他session也买了该商品并产生了订单,那么amount就变成了0,那么这时第二步再执行就有问题。那么采用lock in share mode可行吗,也是不合理的,因为两个session同时锁定该行记录时,这时两个session再update时必然会产生死锁导致事务回滚。以下是操作范例(按时间顺序)

  使用场景一:数据表的状态

    如果存在一张表记录一个商品的状态,在订单的变化过程中,订单的状态是不断变化的,而且变化的过程中肯定也会有并发的问题,而且很多时候与其他系统有交互,会存在补偿的情况,所以并发的可能性很大,补偿或者为了增加状态修改的成功可能性,2次改变状态的情况也有,楼主就遇到了这种情况,真操蛋。于是看到有这样的for update写法。

    1  update order set status = 1 where product_id = '1';   

    2 insert order_flow  (..............) value (.........)

    这样的情况下就有可能订单的状态已经更新完成了,但是补偿这些额外的消息把状态又更新为待处理或者插入了多条流水的情况(多条流水的可能性大,状态的那种可能补偿滞后)。这个时候就可以使用select .... from order where order_id = '1' for update,先锁住要修改状态的表,这样就不会别人操作了,自己先后面把流水插入,然后更新状态,完美。但是加了锁之后性能就很慢了,担心性能影响,而且有可能存在死锁的情况,后面我就修改为流水表中增加一个唯一索引,这样插入流水报错就是已经处理过的记录了。这样就不会存在性能问题。

  通过对比,lock in share mode适用于两张表存在业务关系时的一致性要求,for  update适用于操作同一张表时的一致性要求。

Mysql的排他锁和共享锁的更多相关文章

  1. 【问答分享第一弹】MySQL锁总结:MySQL行锁、表锁、排他锁、共享锁的特点

    大家好,我是小于哥哈.前几天能分享了第一期面试题,MySQL 中有哪几种锁 和 这些锁各有哪些特点 ,这道面试题是经常会被问到的一个面试题,大家反馈的都挺不错的.今天特此来总结一下. 首发于公众号[终 ...

  2. [数据库事务与锁]详解六: MySQL中的共享锁与排他锁

    注明: 本文转载自http://www.hollischuang.com/archives/923 在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大 ...

  3. mysql共享锁与排他锁

    mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能 ...

  4. 【数据库】MySQL中的共享锁与排他锁

    转载:http://www.hollischuang.com/archives/923 在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库 ...

  5. 【转】MySQL中的共享锁与排他锁

    在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突.行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁及排他锁的概念.使用方式及 ...

  6. MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  7. 转 MySQL中的共享锁与排他锁

    原文链接在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突.行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁及排他锁的概念.使 ...

  8. MySQL中的共享锁与排他锁

    MySQL中的共享锁与排他锁 在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突.行级锁分为共享锁和排他锁两种,本文将详细介绍共 ...

  9. Mysql的共享锁和排他锁(转载)

    mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能 ...

随机推荐

  1. Linux常用命令简单总结

    Liunx常用命令 1. 文件及目录管理 1.1. ls:显示目录 参数及说明 空:补显示隐含文件 -a:显示所有文件 -l:显示详细列表 1.2. chgrp:设置文件组(root权限) 用法示例 ...

  2. 7-zip 解压

    7-zip 解压 1.引入依赖文件 sevenzipjbinding.jar sevenzipjbinding-Allwindows.jar <!-- https://mvnrepository ...

  3. 学生管理系统开发代码分析笔记:jsp+java bean+servlet技术

    1 序言 学习java web的时候很渴望有一份完整的项目给我阅读,而网上的大部分项目拿过来都无法直接用,好不容易找到了一个学生管理系统也是漏洞百出.在此,我将边修改边学习这份代码,并且加上完全的注释 ...

  4. memcached常用命令

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt104 一.Memcache面向对象的常用接口包括:Memcache::con ...

  5. webpack2学习日志

    webpack说容易也容易,说难也难,主要还是看个人,想学到什么样的程度,很多公司可能要求仅仅是会用就行,但是也有一些公司要求比较高,要懂一些底层的原理,所以还是要花一些时间的,看个人需求.这篇仅仅是 ...

  6. Java学习记录:文件的输入输出流

    Java中的输入.输出流中可以用于文件的读写,拷贝. 由于文件都是由字节组成的,可以将文件中的内容以字节的方式读取出来. 输入流还可以直接转换为图片来使用.其实ImageIcon提供了方法可以直接打开 ...

  7. PHP(函数)

    <script> // 获得日 var time = new Date(); var x = time.getDate(); document.write(x+"日," ...

  8. python--用户登录验证

    目标要求: 1.最多输入3次用户名密码, 2.如果是被锁用户,则一次即退出程序, 3.如果输入正确的用户名密码,则提示登陆成功,程序结束, 4.3次输入不对,会将用户写入被锁用户列表,当然,该用户名需 ...

  9. 【2017集美大学1412软工实践_助教博客】团队作业10——项目复审与事后分析(Beta版本)

    写在前面的话 转眼轰轰烈烈本学期的软工实践就结束了,这个过程中想必在熬夜敲代码,激烈讨论中留下诸多回忆的同时,也收获了不少.恭喜所有团队完成了本阶段冲刺,此外,由于大家的贡献分给的都很平均,将个人贡献 ...

  10. Java第六周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...