转 http://www.cnblogs.com/chenwenbiao/archive/2012/06/06/2537508.html

CREATE TABLE `products` (
`id` int() NOT NULL AUTO_INCREMENT,
`name` varchar() NOT NULL,
`quantity` int NOT NULL,
`cityid` varchar() DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_of_cityid` (`cityid`,`id`)
) ENGINE=InnoDB; insert into products (name,quantity,cityid) values ('牙刷',, );
insert into products (name,quantity,cityid) values ('大米',,);
insert into products (name,quantity,cityid) values ('豆角',,);
insert into products (name,quantity,cityid) values ('苹果',,);

不安全的做法:

SELECT quantity FROM products WHERE id=3;

UPDATE products SET quantity = quantity -1 WHERE id=3;

第一个访问者                                                                                第二个访问者

A)SELECT quantity FROM products WHERE id=3;                                  

                                   C)SELECT quantity FROM products WHERE id=3;

                                         

B)UPDATE products SET quantity = quantity -1 WHERE id=3;

                                  D)UPDATE products SET quantity = quantity -1 WHERE id=3;

假设两次访问前quantity数量为10

第一个访问者执行select后,得到 quantit7=10,

第二个访问者到达,由于CPU时间片分配,将控制权给了第二个访问者,通过select,得到quantity=10

再次时间片轮循,第一个访问者执行B SQL后,quantity=9

第二个访问者执行D SQL 后,quantity仍然为9,因为第二个访问者并不知道第一个访问者的存在, 这就出问题了

解决方法

最简单的就是加 悲观锁, 缺点:若锁的时候过长,其他用户无法访问,影响并发性,加锁,会增加额外开销

或者应用层利用乐观锁, 并发大的情况下较好,避免加锁

第一个访问者                                                                                第二个访问者

A)SELECT quantity FROM products WHERE id=3 for update;                                  

                                   C)SELECT quantity FROM products WHERE id=3 for update;

                                         

B)UPDATE products SET quantity = quantity -1 WHERE id=3;

                                  D)UPDATE products SET quantity = quantity -1 WHERE id=3;

sql执行如下

A窗口

此时,在B窗口,再执行一遍select

被锁住, for update 悲观锁,也称为排他锁,不允许他人读/写

A窗口,执行commit

此时B窗口

即可看见 id=1的记录

另外,当select ... where for  update 中的where条件不是主键,哪怕是其他索引时,也会锁表,

A窗口

B窗口

当A窗口,commit后,B窗口者返回数据, 尽管cityid为索引,但也发生了表锁

当为主键时,才行锁

A窗口,不commit

B窗口取数据,马上返回数据

二.乐观锁

在表中加一个列 version, update更新后就加1

在访问前假设  version=10

第一次访问                                                   第二次访问

A) select quantity, version from products;

                       C) select quantity, version from products; 

B) update products set version=version+1,quantity=quantity-1 where version=10 and id=1

                       D) update products set version=version+1,quantity=quantity-1 where version=10 and id=1 

当第一个访问者执行B后,version已由10,变成了11

当第二个访问者执行D后,找不到version=10的记录,影响的记录为0,需要重试几次

          

innodb 悲观锁,乐观锁的更多相关文章

  1. Java并发 行级锁/字段锁/表级锁 乐观锁/悲观锁 共享锁/排他锁 死锁

    原文地址:https://my.oschina.net/oosc/blog/1620279 前言 锁是防止在两个事务操作同一个数据源(表或行)时交互破坏数据的一种机制. 数据库采用封锁技术保证并发操作 ...

  2. Hibernate悲观锁/乐观锁

    如果需要保证数据访问的排它性,则需对目标数据加"锁",使其无法被其它程序修改 一,悲观锁 对数据被外界(包括本系统当前的其它事务和来自外部系统的事务处理)修改持保守态度,通过数据库 ...

  3. SQL Server 锁机制 悲观锁 乐观锁 实测解析

    先引入一些概念,直接Copy其他Blogs中的,我就不单独写了. 一.为什么会有锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 1.丢失更新 A,B两个用户读同一数据并进行修改,其中 ...

  4. 最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

    在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 01.乐观锁 vs 悲观 ...

  5. Java最全锁剖析:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

    乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用. 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会 ...

  6. Optimistic concurrency control 死锁 悲观锁 乐观锁 自旋锁

    Optimistic concurrency control https://en.wikipedia.org/wiki/Optimistic_concurrency_control Optimist ...

  7. MySQL/InnoDB中,乐观锁、悲观锁、共享锁、排它锁、行锁、表锁、死锁概念的理解

    文章出处:https://www.souyunku.com/2018/07/30/mysql/?utm_source=tuicool&utm_medium=referral MySQL/Inn ...

  8. MySQl中隔离级别和悲观锁乐观锁

    1.MySql的事物支持 MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关: MyISAM:不支持事务,用于只读程序提高性能 InnoDB:支持ACID事务.行级锁.并发 Ber ...

  9. 【MySQL】悲观锁&乐观锁

    悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念.本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍. 悲观锁(Pessimistic Lock) 悲观锁的 ...

随机推荐

  1. Node.js之【正则表达式函数之match、test、exec、search、split、replace使用详解】

    1. Match函数 使用指定的正则表达式函数对字符串惊醒查找,并以数组形式返回符合要求的字符串 原型:stringObj.match(regExp) 参数: stringObj 必选项,需要去进行匹 ...

  2. php mysqli多个查询的例子

    php中Mysqli多个查询的例子,感兴趣的朋友可以参考下. php中Mysqli多个查询的例子,感兴趣的朋友可以参考下. mysqli_multi_query(mysqli link,string ...

  3. 关于yum与源码安装的LAMP或LNMP网页直接显示空白页的问题?

    学习LAMP.LNMP时,遇到很奇怪的问题就是:搭建完LAMP或LNMP环境后安装PHPweb程序时,Discuz和Wordpress打不开安装向导,直接显示空白页(PHPWind9.0除外),没有任 ...

  4. WRS是什么?

    全球参考系(WRS)是为卫星下行数据服务而建立的一种全球符号坐标系统,本文详细介绍了Landsat卫星的轨道特性,给出了相应的WRS网格坐标位置的估算方法,并给出了估算的结果。对该方法的研究为地面应用 ...

  5. 微软职位内部推荐-Senior Network Engineer

    微软近期Open的职位: Global Foundation Services is the team behind the cloud. GFS is responsible for deliver ...

  6. github简单使用

    github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开.对于一般人来说公共仓库就已经足够了,而且我们也没多少代码来管理,O(∩_∩)O ...

  7. Duilib介绍以及各个类的简介

    转自http://note.sdo.com/u/icez/n/mvO-X~jyVnpFnM01A0000m DirectUI意为直接在父窗口上绘图(Paint on parent dc directl ...

  8. jquery1.8在ie8下not无效?

    // 不需要的name加到下面 var excludes = ['name1', 'name2', 'name3'];   $.each(excludes, function (i, v) {   e ...

  9. 1060: [ZJOI2007]时态同步 - BZOJ

    Description小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的 ...

  10. 原生js解决跨浏览器兼容问题

    //跨浏览器兼容问题 Util = { //添加类名 add : function(ele,type,hand){ if(ele.addEventListener){ ele.addEventList ...