在说具体的锁结构时,先思考一个问题,那就是为什么要上锁?然后我要如何选择锁?锁具体如何实现?

在文章得末尾我给出了我的个人答案。

一、什么是悲观锁?

  1、悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过获取锁才能进行对相同数据的操作,这点跟java中的synchronized很相似。

  2、在MySQL中如何实现悲观锁。?

  mysql中有悲观锁的实现,我们想实现悲观锁时调用相对应得语句。

  测试用表的结构和插入一行数据,下面其他的锁也会同时用到这个表。

 use test;
 create table msq_test (
   id int primary key,
   status  ) engine = innodb default character set = 'utf8';

 , '1');

  操作:1、set autocommit=0;  2、select  .....for update实现锁

  注意:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。我们可以使用命令设置MySQL为非autocommit模式:set autocommit=0;

  

    //开始事务
    begin;
    //查询出主键id=1的信息
     for update;
    //修改status为2
    ;
    //提交事务
    commit;

注:上面的begin/commit为事务的开始和结束,因为在前一步我们关闭了mysql的autocommit,所以需要手动控制事务的提交

  在这里,我们使用了select…for update的方式,这样就通过数据库实现了悲观锁。此时在msq_test表中,id为1的 那条数据就被我们锁定了,其他事务的操作必须等待我们自己主动commit提交事务之后才能操作,这样我们可以保证当前的数据不会被其它事务修改。

二、什么是乐观锁 ?

  1、乐观锁就是每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

  2、在mysql如何实现乐观锁?

  乐观锁不是数据库自带的,需要我们自己去实现

  

 use test;
 create table msq_test (
 d int primary key,
 status ),
 version not null
 ) engine = innodb default character set = 'utf8';

 , );

  在上表中添加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。

  

;//得出一开始设置得version字段(versionValue)
   where version = versionValue;

  这样子就实现了乐观锁机制。

三、什么是行锁和表锁?

  行锁:

    行锁,由字面意思理解,就是给某一行加上锁,也就是一条记录加上锁。

"  lock in share mode; 

在msq_test表中,id字段为主键,就也相当于索引。执行加锁时,会将id这个索引为1的记录加上锁,那么这个锁就是行锁。

到这里,我一开始也是很懵逼,啥是 lock in share mode???

select.....lock in share mode走的是IS锁(意向共享锁),即在符合条件的rows(行)上都加了共享锁,这样的话,其他session(事务)可以读取这些记录,也可以继续添加IS锁,但是无法修改这些记录直到你这个加锁的session执行完成(否则直接锁等待超时)。

  表锁:

    根据行锁,你能理解啥是表锁吗?我想你智商比我高,应该可以。

    不过我们需要注意一些锁的级别,MySQL InnoDB默认Row-Level Lock,所以只有「明确」地指定主键,MySQL 才会执行Row lock (只锁住被选取的数据) ,否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。

四、排他锁

  1、什么是排他锁

    若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A。

    啥?这定义太过复杂,难道买菜我会需要用高数去计算菜钱?我也觉得没必要。所以可以认为上了排他锁,其他线程既不能读也不能修改。

  2、如何用排他锁

    用法: select … for update;

    例如:select * from msq_test where id = 1 for update;

    排他锁的申请前提:没有线程对该结果集中的任何行数据使用排他锁或共享锁,否则申请会阻塞。

    for update仅适用于InnoDB,且必须在事务块(BEGIN/COMMIT)中才能生效。在进行事务操作时,通过“for update”语句,MySQL会对查询结果集中每行数据都添加排他锁,其他线程对该记录的更新与删除操作都会阻塞。排他锁包含行锁、表锁。

  注意:

    事务保证整个操作的成一个组,要么全做要么全不做 但是不能保证多个事务同时读取同一个数据
    数据对象被加上排它锁时,其他的事务不能对它读取和修改;加了共享锁的数据对象可以被其他事务读取,但不能修改

文章的末尾,回到一开始的问题,为何要上锁?锁的具体实现上文已经给出。

  答:为何上锁?

  事务可以用锁实现,可以保证一致性和隔离性,但是锁用来保证并发性;但是隔离性只是保证不会出现相互读取中间数据(却无法解决并发的问题)

  为啥保持一致性的原因: MySQL会出现丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。例如:用户A把值从11改为8,用户B把值从8改为11,则用户A丢失了他的更新。
        为啥保持隔离性的原因:MySQL会出现脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取。例如:用户A,B看到的值都是9,用户B把值改为5,用户A读到的值仍为9。

  

    

悲观锁,乐观锁,排他锁,行锁----MYSQL的更多相关文章

  1. MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 7) --行锁功能:怎么减少行锁对性能的影响? MySQL的行锁是在引擎层由各个引擎自己实现的.因此,并不是所有的引擎都支持行锁,如 ...

  2. 极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间

    极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间 笔记体会: 方案一,事务相 ...

  3. MySQL 啥时候用表锁,啥时候用行锁?

    大家好,我是树哥. MySQL Innodb 的锁可以说是执行引擎的并发基础了,有了锁才能保证数据的一致性.众所周知,我们都知道 Innodb 有全局锁.表级锁.行级锁三种,但你知道什么时候会用表锁, ...

  4. Mysql锁机制--索引失效导致行锁变表锁

    Mysql 系列文章主页 =============== Tips:在阅读本文前,最好先阅读 这篇(Mysql锁机制--行锁)文章~ 在上篇文章中,我们看到InnoDB默认的行锁可以使得操作不同行时不 ...

  5. MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)

    转载. https://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...

  6. MySQL锁(行锁、表锁、页锁、乐观锁、悲观锁等)

    锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一 ...

  7. MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)

    原文地址:http://blog.csdn.net/mysteryhaohao/article/details/51669741 锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是 ...

  8. MySQL中的锁(表锁、行锁)

    锁是计算机协调多个进程或纯线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所在有数 ...

  9. Mysql研磨之InnoDB行锁模式

    事务并发带来的一些问题 (1)更新丢失(LostUpdate):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题最后的更新覆盖了由其 ...

  10. MySQL高级知识(十四)——行锁

    前言:前面学习了表锁的相关知识,本篇主要介绍行锁的相关知识.行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率低,但并发度高. 0.准备 #1.创建相关测试表tb_ ...

随机推荐

  1. JS两个页面通过URL传值

    1.传递参数: window.location.href = "./list.html?id="+id; 1.接收参数: (1)接收参数函数封装 function GetReque ...

  2. pacbio bax.h5文件处理及ccs计算

    1.NCBI文件格式如下: 2.格式转换 (1) bas.h5 -> ccs source /share/nas2/genome/biosoft/smrtanalysis/2.3.0/smrta ...

  3. Power BI Desktop 新年快乐!

    新年快乐 2018年是Power BI 多产的一年!更新发布的功能就超过150多个,真是相当的强大! 为了庆祝这一成功的一年,Power BI官方团队制作了一个有趣的视频,展示他们对2018年最喜欢的 ...

  4. sqlite数据库操作

    1.创建表 import sqlite3 conn = sqlite3.connect('C:\\Users\\Kuma\\Desktop\\spider.db') print('connect su ...

  5. alpha冲刺(1/10)

    前言 队名:旅法师 作业链接 队长博客 燃尽图 会议 会议照片 会议内容 陈晓彬(组长) 今日进展: 召开会议 安排任务 博客撰写 构建之法的阅读 问题困扰: Java的学习感觉无从下手,学基础语法好 ...

  6. PTA——组合数

    PTA 7-48 求组合数 #include<stdio.h> double fact(int n); int main() { int m,n; int c; scanf("% ...

  7. session and cooike

    一.理解Cookie Cooie的作用: 当一个用户通过HTTP访问一个服务器时,这个服务器会将一些Key/Value键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访 ...

  8. python:用wordcloud生成一个文本的词云

    今天学习了wordcloud库,对<三国演义>生成了词云图片,非常漂亮.就想多尝试几个,结果发现一系列问题.最常出现的一个错误就是"UnicodeDecodeError : .. ...

  9. 安卓控制LED驱动编写

    开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 打开Android Stud ...

  10. Python 解决: from pip import main ImportError: cannot import name 'main'

    此次报错是因为 pip 升级出的问题: from pip import mainif __name__ == '__main__': sys.exit(main()) 改为: from pip imp ...