mysql锁的分类
Mysql中锁的分类按照不同类型的划分可以分成不同的锁,按照「锁的粒度」划分可以分成:表锁、页锁、行锁;按照思想的划分:「乐观锁」和「悲观锁」。
1.表锁
行级锁定最大的特点就是锁定对象的粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
mysql中使用行级锁定的主要是InnoDB存储引擎。
InnoDB的行级锁定按使用方式同样分为两种类型,共享锁和排他锁,而在锁定机制的实现过程中为了让行级锁定和表级锁定共存,InnoDB也同样使用了意向锁(表级锁定)的概念,也就有了意向共享锁和意向排他锁这两种。
对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);
对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。
共享锁(S):SELECT*FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X):SELECT*FROM table_name WHERE ... FORUPDATE
2.共享锁
共享锁又称读锁 (read lock),是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。当如果事务对读锁进行修改操作,很可能会造成死锁。
3.排它锁
排他锁 exclusive lock(也叫 writer lock)又称写锁,排它锁是悲观锁的一种实现。FORUPDATE
仅适用于Innodb, 且必须在事务处理模块(BEGIN/COMMIT)中才能生效 。
提示
若某个事物对某一行加上了排他锁,只能这个事务对其进行读写,在此事务结束之前,其他事务不能对其进行加任何锁,其他进程可以读取,不能进行写操作,需等待其释放。
排它锁细分种类:https://zhuanlan.zhihu.com/p/420761461
InnoDB行锁优化建议
1.表操作优化
- 尽可能让所有的数据检索都通过索引来完成,从而避免InnoDB因为无法通过索引键加锁而升级为表级锁定;
- 合理设计索引,让InnoDB在索引键上面加锁的时候尽可能准确,尽可能的缩小锁定范围,避免造成不必要的锁定而影响其他Query的执行;
- 尽可能减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录;
- 尽量控制事务的大小,减少锁定的资源量和锁定时间长度;
- 在业务环境允许的情况下,尽量使用较低级别的事务隔离,以减少MySQL因为实现事务隔离级别所带来的附加成本。
2.减少死锁产生概率?
- 类似业务模块中,尽可能按照相同的访问顺序来访问,防止产生死锁;
- 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
- 对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率。
提示
innodb 的行锁是在有索引的情况下,没有索引的表是锁定全表的。
发生死锁如何解决?
1. 查看当前运行的所有事务
SELECT * FROM information_schema.innodb_trx
2.停止事务
KILL 165667 ; KILL 后面的数字指的是 trx_mysql_thread_id 值。