数据库--锁机制

1.共享读锁
共享读锁是基于存储引擎MyISAM中读锁的,MyISAM是表锁。

首先是事务A加读锁,此时自己是可以进行读操作的。
数据库--锁机制
在事务B中再进行查询操作,发现仍然是可以的。
数据库--锁机制
可以得出读锁read是共享读锁,即一个事务添加读锁的时候,其他的事务也可以读。

2.独占写锁
它也是基于存储引擎MyISAM中写锁。

(1)事务A自己加读锁,然后自己进行写操作,发现提示错误,是不允许的。
数据库--锁机制
(2)事务A加读锁,在事务B中写操作呢?
数据库--锁机制
那么会出现等待的情况,等待事务的读锁解锁之后,它才会修改成功。
数据库--锁机制
(3)事务A加写锁,此时它自己是可以进行读和写操作的。
数据库--锁机制
(4)事务A加写锁,事务B进行读取,会出先等待的情况,等事务A解锁后,才会输出。
原来的数据是这样的:
数据库--锁机制
随后事务A加写锁,事务B查询会等待,事务A解锁后,才会查询出内容。
数据库--锁机制
(5)事务A加写锁,事务B修改呢?
仍然会阻塞,而且事务A解锁后才修改成功。

综上,如果事务A添加了写锁,那么事务B无论是读还是写都是不可以的,即写锁与读锁、写锁都是不兼容的,所以称写锁为独占写锁

3.共享锁
共享锁是基于存储引擎INnoDB中读锁的,INnoDB是行锁(粒度小)
读锁是这样加的:
数据库--锁机制
此时,在事务B中添加读锁也是可以的:
数据库--锁机制
可以得出,读锁和读锁是共享的,所以称之为共享锁

4.排它锁
排它锁基于存储引擎INnoDB中写锁。
如下是加写锁的样例,因为是行锁,所以加锁的时候需要指定某一行:
数据库--锁机制
加锁样例:
数据库--锁机制
现在就是加上了写锁。

下一步就是验证加上写锁之后,其他的事务都可以做些什么呢?
在这里由于INnoDB支持事务,而一句查询语句也是事务,在事务结束后,即分号之后,会把所有的锁、资源都释放掉。
事务A加写锁:
数据库--锁机制
事务B无论是读取还是修改都是可以的:
数据库--锁机制

---------------------------
接下来为了更好的说明排它锁,将事务的自动提交修改一下:

数据库--锁机制
那么这个时候事务A加写锁后,看看B事务可以进行什么操作?
(1)修改本行
数据库--锁机制
如果对已经枷锁的id = 001的这一行修改,那么会失败并阻塞,一段时间后就会提示超时。
(2)修改其他行
给事务A中id = 001加写锁:
数据库--锁机制
修改id = 002的操作成功:
数据库--锁机制
(3)查询
在事务A中id = 001添加写锁后,在事务B中查询
数据库--锁机制
此时要说明一点,就是在INnoDB中,select是不加锁的,insert、update、delete是加写锁的,所以此时是可以操作成功的。
(4)加读锁
这才是真正的加读锁,发现读锁和写锁是不兼容的:
数据库--锁机制
发现加读锁会失败,阻塞。
综上,写锁和读锁不共存、写锁和写锁不共存,所以称之为排它锁

注意:
在这里还有一种情况,就是在加锁的时候,锁并没有加在主键上,此时锁的粒度会增大,变成了表锁。
数据库--锁机制
前面我们已经验证过,如果是只有id = 001这一行锁住了,那么修改id = 002会成功,但是现在失败了,阻塞,只能说明锁是表锁,把整张表都锁住了。
这个时候就是如果是索引查询,列属性有索引结构,那么就是行锁;如果没有索引结构,那么就是表锁

5.悲观锁
提前加锁:MyISAM表锁、INnoDB行锁
6.乐观锁
添加版本标识
7.意向锁
防止死锁
8.间隙锁
解决幻读