## 5.1 mysql 锁定机制
> InnonDB 支持行级锁也支持表级锁,默认行级锁
> MyISAM 采用的是表级锁
* 行级锁
行级锁最大特点是锁定对象的颗粒度很小,发生锁定资源争用的概率很小,能够给于程序尽可能大的并发处理能力,提高一些需要高并发应用系统的整体性能。
由于行级锁颗粒度比较小,所以每次获取锁和释放锁消耗比较大,因此加锁比较慢,很容易发生死锁。
> InnoDB 实现了两种类型的行级锁,包括**共享锁**和**排他锁**,而在锁定机制的实现过程中为了让行级锁定和表级锁定共存,InnoDB使用了两种内部使用的意向锁,也就是意向共享和意向排他锁。
1.共享锁(S):允许一个事务读一行数据时,阻止其他的事务读取相同数据的排它锁,
2.排它锁:允许获得排它锁的事务更新数据,阻止其他事务取得相同数据的共享锁和排他锁。
3.意向共享锁:事物打算给数据行加行共享锁,事物在给一个数据行加共享锁前必须先取得该表的IS锁
4.意向排它锁:事务打算给数据行加行排它锁。
> 对于select InnoDB不会加任何锁,对于insert 、 update 、 delete语句,InnoDB会自动给涉及的数据加排它锁
* 表级锁
表级锁锁定机制的 颗粒度最大,特点开销比较小,逻辑简单,每次锁定整张表,很好的避免了死锁的问题
表级锁锁定机制颗粒很大,所以发生冲突概率最大,表级锁机制下并发度也最低
mysql 下表级锁分为:**读锁定**,**写锁定**
* 页级锁定
页级锁定在MySQL中是比较特殊的一种锁定机制,页级锁定的特点是颗粒度介于行级锁定与表级锁定之间,所以获取锁定所需要的资源开销,以及锁提供的并发处理能力也介于表级锁定和行级锁定之间
## 5.2 MyISAM 表级锁
mysql 的表级锁有两种模式:**表共享读锁**和**表独占写锁**
MyISAM表读操作不会因为不同进程访问资源而**发生阻塞**,对于写操作会阻塞其他用户对同一表的读和写
* mysql 数据库可以通过检查table_locks_waited (出现比较锁定争用而发生等待的次数)和 table_locks_immediate(产生表级锁定的次数) 状态变量来分析系统上表锁争夺情况
`mysql > show status like 'table%'`
* MyISAM 执行查询语句 会自动给查询语句涉及的数据库表记录添加读锁,而在执行数据更新操作会自动给涉及的表记录添加写锁。
* 手动添加读写锁方法,通常使用命令LOCK TABLE 和 UNLOCK TABLE 实现手动加表级锁。
> 如果一个线程获得对一个表的读锁,该线程只能从该表中读取数据;如果一个线程获得对一个表的**写锁**,那么**该线程**只可以**对表进行写数据**,此时**其他线程会被阻塞**,直到写被释放为止
* MyISAM 表锁优化建议
myisam 表级锁的颗粒比较大,在数据库并发处理过程中产生的数据资源争用的情况也会比其他的锁定级别要多,从而在较大程度上会降低并发处理能力。
> 1. myisam 表锁锁定级别是固定的,所以考虑myisam表级锁优化时,重点考虑如何提高并发的效率。
> 2. 减少锁定时间,尽量让查询时间尽可能的短。减少复杂的查询语句,可以考虑复杂的查询分解成多个小的查询。尽可能简历足够高效的索引,让数据检索更迅速。
>3.myisam 表级锁可以考虑分离能并行的操作
## 5.3 InnoDB 行级锁
* 行级锁模式 innoDB 存储引擎支持行级锁,支持事物处理。 事务是由一组sql语句组成的逻辑单元, 特性如下:
> 1. 原子性 : 事务具有原子不可分割的特性,要么一起执行,要么都不执行。
2.一致性: 在事务开始和结束时,数据都要保持一致性。
3.隔离性:在事务开始和结束过程中,事务保持着一定的隔离特性,保证事务在不受外部并发数据操作的影响。
4.持久性:事务完成后,数据将会被持久化数据库中
* InnoDB 行级锁的实现方法
行级锁是通过给索引上的索引项加锁来实现的,InnoDB行级锁只有通过索引条件检索数据,才使用行级锁;否则,InnoDB将使用表锁;
* InnoDB 行级锁优化建议
在锁定方面行级锁的颗粒更小,实现更为复杂,所带来的性能损耗也比表级锁更高;但是,InnoDB行锁在并发性能上远远要高于表锁定,当系统并发较高的时候,优势很明显。
> 1.控制事务的大小,减少锁定的资源量和锁定时间长度。
2.让所有的数据检索都通过索引来完成,从而避免因为无法通过索引加锁而升级为表级锁
3.减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录
4.在业务环节允许的情况下,尽量使用较低级别的事务隔离,以减少因为事务隔离级别锁定带来的附加成本。
5.合理使用索引,让innodb 在索引上面加锁的时候更加精准
6.在同一个事务中,尽可能做到一次锁定所有的资源,减少产生死锁的几率。
7.对于容易产生死锁的业务,可以放弃使用InnoDB行级锁定,尝试使用表级锁定来减少死锁产生的概率
8.不要申请超过实际需要的所级别