分类
从对数据库操作的类型分,分为读锁和写锁
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响
写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁
读锁会阻塞写,但是不会阻塞读。而写锁则会把读和写都阻塞。
从对数据操作的粒度分,分为表锁和行锁
表锁偏向MyISAM存储引擎,开销小,加锁快,无思索,锁定粒度大,发生锁冲突的概率最高,并发度最低
行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB与MYISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。
表锁操作
手动加表锁:lock table 表名称 read(write),表名称2 read(write),其他;
查看加过的锁:show open tables;
删除表锁:unlock tables;
分析表锁:检查table_lock_waited和table_locks_immediate状态变量来分析系统上的表锁定
table_locks_immediate:产生表级锁定的次数,表示可以立即获取锁的查询次数,每立即获取锁值加1
table_locks_waited:出现表级锁定争用而发生等待的次数(不能立即获取锁的次数,每等待一次锁值加1),此值高则说明存在着较严重的表级锁争用情况。
行锁操作
行锁相关系统变量:show status like 'innodb_row_lock%';
Innodb_row_lock_current_waits: 当前正在等待锁定的数量
Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg: 每次等待所花平均时间
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花时间
Innodb_row_lock_waits:系统启动后到现在总共等待的次数
InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁
间隙锁是innodb中行锁的一种, 这种锁锁住多行(数据范围)。间隙锁的主要作用是为了防止出现幻读,对于范围内不存在的key也会锁住导致(无法insert)。
控制间隙锁的参数是:innodb_locks_unsafe_for_binlog, 这个参数默认值是OFF, 也就是启用间隙锁; 当值为true时表示disable间隙锁。这个参数会影响到主从复制及灾难恢复;
间隙锁的出现主要集中在同一个事务中先delete 后 insert的情况
优化建议
尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
合理设计索引,尽量缩小锁的范围
尽可能减少检索条件,避免间隙锁
尽量控制事务大小,减少锁定资源量和时间长度
尽可能低级别事务隔离