在一些面试和书籍上经常会提到各种数据库锁以及事务,在这里结合一些资料简要概括下:
数据库并发需使用事务来控制,事务并发问题需要数据库锁来控制,数据库锁是跟并发控制和事务联系在一起的。
事务:必须满足:ACID(原子性,一致性,隔离性,持久性)四特性,事务是恢复和并发控制的基本单位。
原子性:是事务是数据库的逻辑工作单位,事务中操作要么都做,要么都不做。
一致性:事务的执行结果必须是使数据库从一个一致性状态变大另一个一致性状态,一致性和原子性密切相关的。
隔离性:是一个事务执行不能被其他事务干扰。
持久性:是一个事务一旦提交,他对数据库中数据的改变就是永久性的。
共享锁:共享锁指的就是对于多个不同的事务,对同一个资源共享同一个锁。
排它锁:与共享锁相对应,就是指对于多个不同的事务,对同一个资源只能有一把锁。
对共享锁类型,需在执行的语句后面加上for update
写锁:排他锁又称写锁。
读锁:共享锁又称读锁。
悲观锁:悲观锁是由数据库自己实现的,要用的时,直接调用数据库的相关语句即可。大致理解为觉得在读数据库的时候,
别人可能刚好在写自己刚读的数据,其实就是持一种比较保守的态度。
乐观锁:不是数据库自带的,需要我们自己去实现。乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导
致冲突。在操作数据时,并不进行任何其他的特殊处理(也就是不加锁),而在进行更新后,再去判断是否有冲突了。
行级锁:行锁,字面意思上理解,即是给某一条记录加锁。这是一种排他锁,防止其他事务修改此行。
行级锁分为共享锁和排它锁。
在使用以下语句时, Oracle会自动应用行级锁:
INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT];
表级锁:分为5类:
页级锁:BDB支持页级锁。页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突
少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
补充:
共享锁和排它锁是具体的锁,是数据库机制上的锁,存在以下关系:

(x表示是排它锁(Exclusive),s表示共享锁(Share),Y表示yes,N表示no)
上图表示可以共存的锁,如,第二行表示,一个事务T1给某数据加了X锁,则事务T2就不能再给那数据加X锁了,同时也不能再加S锁了,只有到T1事务提交完成之后,才可以。默认来说,当sql脚本修改更新某条记录的时候,会给该条记录加X锁,读的话加的是S锁。
还有就是,并发控制会造成活锁和死锁,就像操作系统那样,会因为互相等待而导致。活锁指的是T1封锁了数据R,T2同时也请求封锁数据R,T3也请求封锁数据R,当T1释放了锁之后,T3会锁住R,T4也请求封锁R,则T2就会一直等待下去,这种处理方法就是采用“先来先服务”策略;死锁就是我等你,你又等我,双方就会一直等待下去,比如:T1封锁了数据R1,正请求对R2封锁,而T2封住了R2,正请求封锁R1,这样就会导致死锁,死锁这种没有完全解决的方法,只能尽量预防,避免,检查,解除死锁。
承上总结死锁原因:
②顺序封锁发,指的是事先对数据对象指定一个封锁顺序,要对数据进行封锁,只能按照规定的顺序来封锁,但是这个一般不
大可能的。
另外,系统如何判断出现死锁呢,毕竟出现死锁不能一直干等下去,要及时发现死锁同时尽快解决出现的死锁。
诊断和判断死锁有两种方法,一是超时法,二是等待图法。
超时法就是如果某个事物的等待时间超过指定时限,则判定为出现死锁;
等待图法指的是如果事务等待图中出现了回路,则判断出现了死锁。
对于解决死锁的方法,只能是撤销一个处理死锁代价最小的事务,释放此事务持有的所有锁,同时对撤销的事务所执行的数据
修改操作必须加以恢复。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/230018.html原文链接:https://javaforall.net
