zoukankan      html  css  js  c++  java
  • MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)

    悲观锁:

      顾名思义,很悲观,就是每次拿数据的时候都认为别的线程会修改数据,所以在每次拿的时候都会给数据上锁。上锁之后,当别的线程想要拿数据时,就会阻塞,直到给数据上锁的线程将事务提交或者回滚。传统的关系型数据库里就用到了很多这种锁机制,比如行锁,表锁,共享锁,排他锁等,都是在做操作之前先上锁。 
       
    行锁:

      下面演示行锁,打开两个mysql命令行界面,两个线程分别执行如下操作:(左边先执行) 
       
      image_1b8uapk3h3pk1kmmpkg1av0v759.png-174kB
       
      左边的线程,在事务中通过select for update语句给sid = 1的数据行上了锁。右边的线程此时可以使用select语句读取数据,但是如果也使用select for update语句,就会阻塞,使用update,add,delete也会阻塞。 
      当左边的线程将事务提交(或者回滚),右边的线程就会获取锁,线程不再阻塞: 
       
      image_1b8ub488p128jhm911gka0hhhm.png-201.2kB
       
      此时,右边的线程获取锁,左边的线程如果执行类似操作,也会被阻塞: 
       
      image_1b8ub6ptr1i0n1j8hg681fir1fnb13.png-236.3kB
       
    表锁: 
       
      上述例子中,如果使用如下语句就是使用的表锁:

    select * from student for update;

    页锁: 

       
      行锁锁指定行,表锁锁整张表,页锁是折中实现,即一次锁定相邻的一组记录。 
       
    共享锁: 
       
      共享锁又称为读锁,一个线程给数据加上共享锁后,其他线程只能读数据,不能修改。 
       
    排他锁: 
       
      排他锁又称为写锁,和共享锁的区别在于,其他线程既不能读也不能修改。 
       
    乐观锁: 
       
      乐观锁其实不会上锁。顾名思义,很乐观,它默认别的线程不会修改数据,所以不会上锁。只是在更新前去判断别的线程在此期间有没有修改数据,如果修改了,会交给业务层去处理。 
      常用的实现方式是使用版本戳,例如在一张表中添加一个整型字段version,每更新version++,比如某个时刻version=1,线程A读取了此version=1,线程B也读取了此version=1,当线程A更新数据之前,判断version仍然为1,更新成功,version++变为2,但是当线程B再提交更新时,发现version变为2了,与之前读的version=1不一致,就知道有别的线程更新了数据,这个时候就会进行业务逻辑的处理。 
       
    通常情况下,写操作较少时,使用乐观锁,写操作较多时,使用悲观锁。

  • 相关阅读:
    AngularJS中的Provider们:Service和Factory等的区别
    解决Eclipse建立Maven项目后无法建立src/main/java资源文件夹的办法
    关于EL表达式不起作用的问题
    Tomcat+Nginx 负载均衡配置,Tomcat+Nginx集群,Tomcat集群
    Java WebService 简单实例
    火狐浏览器中表单内容在表单刷新时候不重置表单信息
    ie文本框内容不居中问题
    javascript call和apply方法
    javascript的词法作用域
    C++提高编程 deque容器
  • 原文地址:https://www.cnblogs.com/huangjianping/p/8058169.html
Copyright © 2011-2022 走看看