Mysql 锁

mysql锁的类型

  • 表锁
  • 行锁

表锁和行锁都有的种类

1
2
3
4
5
共享锁(shared lock),也叫读锁(read lock)
对上锁的数据可读不可改,必须等锁释放后才能对数据进行修改

排他锁(exclusive lock),也叫写锁(write lock)
对上锁的数据不可读不可写,必须等锁释放后才能对数据进行读和写

结论:

1
2
读锁会阻塞写操作,不会阻塞读操作
写锁会阻塞读和写操作

表锁实现的锁机制

表锁实现的效果:

  • 共享锁:锁住整个表,可读取表数据但是不能操作表中的数据,必须等锁释放后才能操作表中的数据
  • 排他锁:锁住整个表,不可读取表数据和操作表数据,必须等锁释放后才能读取或操作表中的数据

表锁的优点:

  • 对整张表加锁
  • 开销小
  • 加锁快
  • 无死锁
  • 锁粒度大,发生锁冲突概率大,并发性低

行锁实现的锁机制

行锁实现的效果:

  • 共享锁:锁住操作的数据,可读取数据但是不能操作数据,必须等锁释放后才能操作数据
  • 排他锁:锁住操作的数据,不可读取数据和操作数据,必须等锁释放后才能读取或操作数据

行锁的优点

  • 对一行数据加锁
  • 开销大
  • 加锁慢
  • 会出现死锁
  • 锁粒度小,发生锁冲突概率最低,并发性高

mysql上锁命令

表锁:

隐式上锁(默认,自动加锁自动释放)

1
select #默认上共享锁
1
insert、update、delete #上排他锁

显式上锁(手动)

1
2
lock table tableName read; #共享锁
lock table tableName write; #排他锁

解锁(手动)

1
unlock tables; # 解锁所有表

行锁:
隐式上锁(默认,自动加锁自动释放)

1
select #不上锁
1
insert、update、delete #上排他锁

显式上锁(手动)

1
2
select * from tableName where id = xxx in share lock; #共享锁
select * from tableName where id = xxx for update; #排他锁

解锁(手动)

1
2
3
1. 提交事务(commit)
2. 回滚事务(rollback)
3. kill 阻塞进程
1
2
为什么上了写锁,别的事务还可以读操作?
因为InnoDB有MVCC机制(多版本并发控制),可以使用快照读,而不会被阻塞。

死锁

什么是死锁?

1
2
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

通俗来讲就是a锁持有数据a,b锁持有数据b,他们同时都在请求对方的数据,但是因为双方都有锁所以进入互相等待状态

产生死锁的四个必要条件

1
2
3
4
5
6
7
8
(1)互斥条件:该资源任意时刻只由一个线程占有
(理解:一个萝卜一个坑,不能一个萝卜两个坑;总结:不能共享)
(2)请求与保持条件:一个进程因请求资源阻塞时,对已有资源保持不放。
(理解:我得不到,你也别想得到。要死一起死,我做不到大公无私,我要死了,还把资源给你。)
(3)不剥夺条件:线程已经获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完才能释放资源
(理解: 只能等,不能抢。我女朋友再好看...你也不能抢,只能等我分手了,你才有机会....)
(4)循环等待条件:若干进程形成一种头尾相接的循环等待资源关系。
(理解:环——多角恋)

避免死锁

1
2
3
4
5
6
7
8
1. 加锁顺序一致,尽可能一次性锁定所需的数据行
2. 尽量基于primary(主键)或unique key更新数据
3. 单次操作数据量不宜过多,涉及表尽量少
4. 减少表上索引,减少锁定资源
5. 尽量使用较低的隔离级别
6. 尽量使用相同条件访问数据,这样可以避免间隙锁对并发的插入影响
7. 精心设计索引,尽量使用索引访问数据
8. 借助相关工具:pt-deadlock-logger

悲观锁和乐观锁

悲观锁

1
总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加(悲观)锁。一旦加锁,不同线程同时执行时,只能有一个线程执行,其他的线程在入口处等待,直到锁被释放。

行锁和表锁就属于悲观锁

乐观锁

1
2
乐观锁顾名思义就是在操作时很乐观,认为操作不会产生并发问题(不会有其他线程对数据进行修改),因此不会上锁。但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS(compare and swap)算法实现。
简单理解:这里的数据,别想太多,你尽管用,出问题了算我怂,即操作失败后事务回滚、提示。

参考文章:

https://learnku.com/articles/39212?order_by=vote_count&

https://segmentfault.com/a/1190000016611415

https://blog.csdn.net/greenfloweryue/article/details/107846958