当前位置: 首页 > 编程笔记 >

Mysql 行级锁的使用及死锁的预防方案

蓝宜
2023-03-14
本文向大家介绍Mysql 行级锁的使用及死锁的预防方案,包括了Mysql 行级锁的使用及死锁的预防方案的使用技巧和注意事项,需要的朋友参考一下

一、前言

    mysql的InnoDB,支持事务和行级锁,可以使用行锁来处理用户提现等业务。使用mysql锁的时候有时候会出现死锁,要做好死锁的预防。

二、MySQL行级锁

    行级锁又分共享锁和排他锁。

    共享锁:

      名词解释:共享锁又叫做读锁,所有的事务只能对其进行读操作不能写操作,加上共享锁后其他事务不能再加排他锁了只能加行级锁。

      用法:

SELECT `id` FROM table WHERE id in(1,2)  LOCK IN SHARE MODE 

结果集的数据都会加共享锁

    排他锁:

      名词解释:若某个事物对某一行加上了排他锁,只能这个事务对其进行读写,其他事务不能对其进行加任何锁,其他进程可以读取,不能进行写操作,需等待其释放。

      用法:

SELECT `id` FROM mk_user WHERE id=1 FOR UPDATE

三、实例应用

<?php
  $uid=$_SESSION['uid'];
  //开启事务
  sql:begin
  //开启行级锁的排他锁
  sql:SELECT `coin` FROM user WHERE id=$uid FOR UPDATE 
  //扣除用户账户钱币
  $res=update user set coin=coin-value where id=1;
  if($res){
   //将用户的提现信息添加到提现表
   sql:insert into user values(null,"{$uid}",value);
   //判断添加结果
   if(add_cash_result){
    sql:commit
   }else{
    sql:rollback
   }
  }else{
   sql:rollback;
  }

    其实步骤不复杂,就是开启事务判断各个结果为真就提交为假就回滚。单个排他锁没有什么问题,当一个表关联到多个排他锁的时候要注意防止发生死锁。

四、死锁

    `id`  主键索引

    `name` index 索引

    `age`  普通字段

    死锁产生的根本原因是两个以上的进程都要求对方释放资源,以至于进程都一直等待。在代码上是因为两个或者以上的事务都要求另一个释放资源。

    死锁产生的四个必要条件:互斥条件、环路条件、请求保持、不可剥夺,缺一不可,相对应的只要破坏其中一种条件死锁就不会产生。

    例如下面两条语句 第一条语句会优先使用`name`索引,因为name不是主键索引,还会用到主键索引

    第二条语句是首先使用主键索引,再使用name索引 如果两条语句同时执行,第一条语句执行了name索引等待第二条释放主键索引,第二条执行了主键索引等待第一条的name索引,这样就造成了死锁。

    解决方法:改造第一条语句 使其根据主键值进行更新

#①
update mk_user set name ='1' where `name`='idis12';
#②
update mk_user set name='12' where id=12;
//改造后
update mk_user set name='1' where id=(select id from mk_user where name='idis12' );

以上所述是小编给大家介绍的Mysql 行级锁的使用及死锁的预防解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!

 类似资料:
  • 主要内容:1.相互排斥,2.保持并等待,4.循环等待如果我们用一个站在四条腿上的桌子来模拟死锁,那么也可以用同时发生的四个条件来模拟四条腿,导致死锁。 但是,如果我们破坏桌子的一条腿,那么桌子肯定会掉下来。如果能够违反四种必要条件之一并且不让它们一起出现,那么就可以防止死锁,这同样发生在死锁上。 下面来看看如何防止每个条件的发生。 1.相互排斥 从资源的角度看,相互关联的部分是资源永远不能同时被多个进程使用,这是公平的,但这是造成死锁的主要原因。如

  • 问题 你正在写一个多线程程序,其中线程需要一次获取多个锁,此时如何避免死锁问题。 解决方案 在多线程程序中,死锁问题很大一部分是由于线程同时获取多个锁造成的。举个例子:一个线程获取了第一个锁,然后在获取第二个锁的 时候发生阻塞,那么这个线程就可能阻塞其他线程的执行,从而导致整个程序假死。 解决死锁问题的一种方案是为程序中的每一个锁分配一个唯一的id,然后只允许按照升序规则来使用多个锁,这个规则使用

  • 本文向大家介绍怎么防止死锁?相关面试题,主要包含被问及怎么防止死锁?时的应答技巧和注意事项,需要的朋友参考一下 尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。 尽量使用 Java. util. concurrent 并发类代替自己手写锁。 尽量

  • 如何理解死锁的原因--即,如何找出哪些事务捕获了哪些锁? 我的Engine.log文件存在以下死锁: 我对日志中描述的内容的看法如下: ***(2)保持锁 记录锁空间id 0页号36025889 n位96表MYDB.MYTABLE trx id 4 271 9072205锁模式X锁rec,但不锁gap 记录锁,堆第27号物理记录:N_Fields72;紧凑格式;信息位0 ***(1)等待授予此锁:

  • 问题内容: 我已升级到最新的Java 7 build 1.7.0_60-b19,但问题仍然存在。 我进行了另一个线程转储,发现了相同的问题:在DefaultCorrelatingMessageHandler锁调用中,所有DefaultMessageListenerContainers(计数为20)都由taskScheduler(entityScheduler-3)锁定。 这是调度程序和聚合器配置:

  • 问题内容: 我发现经典的Java Deadlock Tutorial 中包含对System.out.format的调用将防止死锁的发生,我不知道为什么。 下面的代码是相同的教程,与除的 这是输出: 删除违规行会导致通常的死锁: 对System.out.format的调用是否以某种方式改变了线程获取对象内在锁的方式? 更新: 通过更改代码中启动线程的位置,我能够使系统再次陷入僵局: 这就引出了一个问