一、锁的分类:
1. 按照性能划分:
1.1 悲观锁 : 在悲观锁机制下,读取数据库中的数据时需要加锁,此时不能对这些数据进行修改操作。修改操作时也需要加锁,此时不能对这些数据进行读操作。Mysql中的读锁和写锁都是悲观锁。
1.2 乐观锁: 乐观锁是通过在数据中增加一个version版本号来实现的,在是查询数据库时,会将版本号一起读取出来,当更新数据时,会将版本号加1,将提交的版本与对应的记录版本号进行对比,如果提交的数据版本号大于数据表中当前要修改的数据版本号则对数据进行修改操作,否则,不修改数据表中的数据。
2. 按照操作类型划分:
2.1 读锁: 读锁又称为共享锁或S锁,针对同一份数据,可以加多个读锁而互不影响。
2.2 写锁: 写锁又称为排他锁或X锁,如果当前锁未释放,它会阻塞其他的写锁或读锁。
3.按照数据粒度划分:
3.1 表锁: 就是在在整个数据表上对数据进行加锁和释放锁,典型的特点就是开销比较小,加锁速度快,一般不会出现思索,锁的粒度比较大,发生锁冲突的概率最高,并发度最低。
在MySQL中有两种表级锁模式,一种是表共享锁,另一种是表独占写锁。当一个线程获取到一个表的读锁后,其他线程仍然可以对表进行读操作,但是不能对表进行写操作。当一个线程获取到一个表的写锁后,只有持有锁的线程可以对表进行更新操作,其他线程对数据表的读写操作都会被阻塞,直到写锁释放为之。
3.2 行锁: 就是对在数据行上进行加锁和释放锁,典型特点就是开销比较大,加锁速度慢,可能会出现死锁,锁定的粒度最小,并发度最高。
提示:行锁主要加在索引上,如果对非索引字段进行更新,航所有可能会变成表锁
3.3. 页面锁: 就是在页面级对数据进行加锁和释放锁,对数据的加锁开销介于表锁和行锁之间,可能会出现死锁,锁的粒度介于表锁和行锁之间.并发度一般。
4.按照更细粒度划分:
4.1 间隙锁: 在MySQL中使用范围查询时,如果请求共享锁或排他锁,InnoDB会给符合条件的索引项加锁
例如: 我们执行以下命令:
update account set balance = balance + 100 where id > 5 and id < 16 ;
其他事务无法在(5,16)这个区间插入或修改操作。
4.2 临键锁: 就是行锁和间隙锁的组合,例如上面的例子在区间(5,16)就可以成为临键锁。
二、死锁的产生预防:
1: 产生死锁的条件
互斥条件
不可剥夺条件
请求与保持条件
循环等待条件
只有4个必要条件都满足,才会发生死锁。破坏其中任何一个条件都可以预防死锁,在工作中,我们经常用有序资源分配法和银行家算法来避免死锁。