1、概念
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的 计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一 个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。
按操作类型分类:读锁(共享锁,对于多个读操作可以同时进行,互不干扰),写锁(互斥锁,如果当前写操作没有完成,则无法进行其他的读操作、写操作)
按操作范围分类:表锁(一次性对一张表加锁,如MyISAM),行锁(一次性对一条数据加锁,如InnoDB),页锁
2、表锁(偏读)
表锁偏向MyISAM存储引擎,开销小,加锁快,无死锁,但锁定粒度大,发生锁冲突的概率最高,并发度最低。
1)基本操作
增加表锁: lock table 表名称 read(write),表名称2 read(write),其他;
查看表上加过的锁:show open tables;(1表示加锁,0表示没加锁)
删除表锁:unlock tables;
2)加读锁
总结:如果给A表加了读锁,则当前会话只能对A表进行读操作。其他会话对其他表(A表以外)可以进行读写操作,对A表可以进行读,写需要等待释放锁。
3)加写锁
总结:当前会话对A表加了写锁,可以对A表进行增删改查操作,对不能对其他表进行任何操作。其他会话对A表操作必须等待当前会话释放锁, 才能进行增删改操作。
4)MyISAM操作
5)表锁分析
- 可以通过检查table_lock_waited和table_locks_immediate状态变量来分析系统上的表锁定
Table_locks_immediate:产生表级锁定的次数,表示可以立即获取锁的查询次数,每立即获取锁值加1
Table_locks_waited 出现表级锁定争用而发生等待的次数(不能立即获取锁的次数,每等待一次锁值加1),此值高则说明存在着较严重的表级锁争用情况。
MYISAM的读写锁调度是写优先,这也是MYISAM不适合做写为主表的引擎。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永久阻塞。
3、行锁(偏写)
行锁偏向InnoDB存储引擎,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发度也最高。InnoDB与MYISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。并发会导致更新丢失、脏读、不可重读、幻读。
1)、MySQL有自动提交,oracle没有自动提交
2)间歇锁
3)InnoDB操作
Innodb存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁定会要更高一下,但是在整体并发处理能力方面要远远优于MYISAM的表级锁定的。当系统并发量高的时候,Innodb的整体性能和MYISAM相比就会有比较明显的优势了。 但是,Innodb的行级锁定同样也有其脆弱的一面,当我们使用不当的时候,可能会让Innodb的整体性能表现不仅不能比MYISAM高,甚至可能会更差。
4)行锁分析
通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况
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:系统启动后到现在总共等待的次数
对于这5个状态变量,比较重要的主要是:
Innodb_row_lock_time_avg (等待平均时长)
Innodb_row_lock_waits (等待总次数)
Innodb_row_lock_time(等待总时长)
尤其是当等待次数很高,而且每次等待时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手制定优化计划。
5)优化建议
1、尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
2、合理设计索引,尽量缩小锁的范围
3、尽可能减少检索条件,避免间隙锁
4、尽量控制事务大小,减少锁定资源量和时间长度
5、尽可能低级别事务隔离
参考资料
https://blog.youkuaiyun.com/why15732625998/article/details/80439315