Technology Exchange
免费咨询热线
400-090-9964
1.什么是锁
锁(LOCK)用于管理对共享资源的并发控制。通过建立锁,可以保护资源(数据)的完整性和一致性。
通过一个经典的数据库问题(丢失更新)就可以看到锁的意义:
1)针对同一个数据库,有表 Student,表结构如下: ID、姓名、年龄
2)用户A登录到数据库中,查询Student表的数据,此时标记A的会话为Session1
3)用户B登录到数据库中,查询Student表的数据,此时标记B的会话为session2
4)用户A将Student表中姓名为张三的学生姓名修改为李四,并提交
5)用户B将Student表中姓名为张三的学生的年龄修改为18,并提交
当B提交数据时,他看到的数据是最初提取出来的数据,并做出修改,此时数据库中会存在一条姓名为张三年龄为18的记录。但是在操作4中,用户A明明将张三的姓名修改为了李四,这样明显可以看出,用户A做的修改并没用生效,这种情况称之为丢失更新。虽然整个过程仅仅涉及了Select和Update简单的操作,但产生的问题是很明显的。为此,我们应该对数据共享进行一定的保护,也就引入了锁机制。
2.锁机制
悲观锁定
悲观锁定就如同他的名字一样,数据库“悲观”地认为并发情况下准备修改的数据随时有可能已经被他人修改。因此在用户获取某些数据并有意做出修改时,数据库就对这些数据加上锁,并一直将锁保持至用户提交或回滚当前事务,在此期间其他用户不能对这些数据或数据结构做出修改。正是因为悲观锁定的这种特性,用户必须要保持与数据库的有效的连接状态,而且至少在事务生存期中只有一个用户。一般来说悲观锁定对数据的一致性管理是较为有效的,但是其缺点也较为明显:当并发量较大时,很容易造成阻塞,同时在一些特定的应用环境下,如Web应用,因为很难保证事务生存期中只有一个用户,当多个用户进入这个连接,那么锁的作用就会失效。
乐观锁定
与悲观锁定不同,数据库“乐观”地认为并发情况下准备被修改的数据不会被他人修改,直到最后做提交修改时才加锁并验证数据是否正确。乐观锁定事务开始于最终提交修改,因此对连接的要求几乎没有。但是因为在事务开始前,有可能修改的数据已经被他人修改过,此时会回滚当前的事务,用户做的修改将会失败。采用乐观锁定的要求比悲观锁定要低很多,并且阻塞的时间也非常的短。但因为有可能事务被回退,就需要为此做其他的弥补措施。
阻塞
阻塞发生在用户之间对资源的控制权争夺中,如果一个用户A已经对某个数据持有了锁,另一个用户B又请求获取这个数据的控制权,那么就会产生阻塞。在此期间,用户B的操作会被搁置, 直到用户A提交或回滚当前事务,用户B才能获取到数据的控制权。
死锁
死锁同样发生在资源的控制权争夺中,但是与阻塞最大的区别是:
阻塞是由于资源不足引起的排队等待现象。 死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且所持资源无法释放。
下面通过一个简单的例子介绍死锁产生的一个原因:
1)数据库中存在A、B两表,且两表都只有一条数据
2)用户A进入数据库,此时标记A的会话为Session1
3)用户B进入数据库,此时标记B的会话为Session2
4)用户A修改A表的数据,用户B修改B表的数据
5)用户A再修改B表的数据,用户B再修改A表的数据
进行到操作5时,将产生死锁现象。用户A在等待用户B释放对A表数据的控制权,而用户B又在等待用户A释放对B表数据的控制权,这就引发了死锁的现象。
需要注意的是,Oracle数据库本身几乎不会发生死锁现象,一旦你的应用中出现了死锁的问题,那么一般是设计上存在Bug(如外键中没有创建索引等)。
(以上内容摘于网络,如有侵权,请告之,将第一时间删除)