mysql-锁问题

242 阅读2分钟

悲观锁

A:执行流程

  1. 在任意记录修改时,先给此记录加入排他锁
  2. 如果加锁失败,说明改记录正在被修改,此时需要等待或者抛出异常
  3. 如果成功加锁,对记录进行操作,事务完成进行解锁

B:优点与不足

  1. 安全性高,效率低,加锁带来额外开销,产生死锁问题
  2. 假如是自读型事务,没必要要锁,增加系统负载
  3. 降低并行性,此事务在操作时锁定了那行,其他事务必须等待其完成才能处理那行

c:实例

set autocommit=0;

# 设置完autocommit后,我们就可以执行我们的正常业务了。具体如下:

# 1. 开始事务

begin;/begin work;/start transaction; (三者选一就可以)

# 2. 查询表信息

select status from TABLE where id=1 for update;

# 3. 插入一条数据

insert into TABLE (id,value) values (2,2);

# 4. 修改数据为

update TABLE set value=2 where id=1;

# 5. 提交事务

commit;/commit work;

乐观锁

A:执行流程

  1. 乐观锁认为多用户并发不会彼此相互影响
  2. 乐观锁在每次数据更新时,会检查其他事务是否修改该数据,有则回滚

B:优点与不足

  1. 乐观锁是提交数据时锁定,不会产生任何锁和死锁,但是如果两个数据同时修改返回数据库,就会产生意想不到的问题

c:实例

  • 记录数据版本号,或者时间戳实现乐观锁
  update TABLE
  set value=2,version=version+1
  where id=#{id} and version=#{version};

死锁

A:问题描述

  1. 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象
  2. 如果无外力协助,永远分配不到资源而无法进行下去

B:解决方案

第一种:

  1. 查询是否锁表
  show OPEN TABLES where In_use > 0;
  1. 查询进程(如果您有SUPER权限,您可以看到所有线程。否则,您只能看到您自己的线程)
  show processlist

3.杀死进程id(就是上面命令的id列)

  kill id

第二种:

  1. 查看当前的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
  1. 查看当前锁定的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
  1. 查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 

下列方法有助于最大限度地降低死锁

1.  按同一顺序访问对象。
2.  避免事务中的用户交互。
3.  保持事务简短并在一个批处理中。
4.  使用低隔离级别。
5.  使用绑定连接



参考掘金大佬博客