这是一篇纯纯个人理解的文章。
什么是锁,锁在数据库的读写当中代表着我对当前读写内容的所有权。所以会有各种各样的所有权,
比如我是我的,但是你可以读。这就叫共享锁,(S锁)也即可以有很多的事务去读取这个锁,但是不能修改,就能读。
所以会有另外一个方面,是我的,你就不能动。也就是互斥锁,只能当我对当前的内容进行修改之后释放你才能申请锁。
很自然会想到一个问题,那么一个表超级大,不会操作就全部锁起来吧。这个在读写当中很多细节。
假设有个表
- id name
- 1 tiny
- 2 andy
- 5 sad
- 7 niu
这个也跟检索的情况有关系,比如精确查找。
select * from table where id = 2
直接检索的话,加的是行锁,锁定当前行。我会想到一个问题,就是当前行不存在怎么办。等下回答。
检索是用的大于小于的操作呢。
select * from table where id > 3
这样可以看到会给出id为5,7的两个数据,按照说法是会加表锁,也即将表都加上锁,检索内容。这里id是主键,所以调用聚簇索引查找。
(看到的别的大佬说,其实inndb上不会加表锁,是加的行锁和间隙锁)也即,在(-∞,5)(5,7)(7,+∞)加上间隙锁,然后给5,7加上行锁而形成的。
那么如果搜索的内容不存在呢,比如以下这个检索。
select * from table where id = 4
这里是在5到7之间加上间隙锁。
这就是检索的内容,上述可以说是悲观锁,也即如果我想读取或者当前内容的时候,需要锁上,其他事务无法处理。
这样会增加io等待。
另外一个是乐观锁,也即当给内容加上锁之后,会打上一个version,如果有修改就会增加1,当需要更新的时候,会查看当前version与自己的version是否一致,如果一致需要判断是否可以修改,如果不能修改会返回0,需要重新更新等。
事务隔离方式,
1,Read Uncommited.读未提交,这是最低的一个级别,即有可能读取其他事务还没有提交的内容,也即这个数据还不知道是不是有效数据,也即脏读,读到被修改但是未知是否有用的数据。
2.Read Committed.读已提交。也即其他事务提交以后的数据我方才能读取。可以有效解决读到未提交数据的情况,但是有一个是不可重复读。也即如果事务进行回退,这个数据就不存在啦。
3.repetable read.可重复读。也即可以重复读取的数据,但是有可能造成幻读的情况出现。读取的是备份的数据, 不是真实的数据,
4.串行读。可以解决所有情况,但是消耗较大。
幻读是只存在当前读的时候才会出现,也即加锁之后才会有。
(快照读和当前读)快照读就是读取最新的内容,当前读就是在加锁之后,读取的内容,有可能出现幻读,也即当前行条数不对。
select * form table where id = 1 lock in share mode 、
共享锁
select * from table where id > 3 for update、
排他锁
update 、delete 、insert