锁:
两个锁是可以同时存在于同一资源上的(比如同一个表上)。这被称为共
享锁与共享锁兼容。这意味着共享锁不阻止其它session同时读资源,但阻
止其它session update
排他锁:这个简单,即其它事务既不能读,又不能改排他锁锁定的资源。
意向锁就是说在屋(比如代表一个表)门口设置一个标识,说明屋子里有人(比如代表某些记录)被锁住了。另一个人想知道屋子
里是否有人被锁,不用进屋子里一个一个的去查,直接看门口标识就行了。
当一个表中的某一行被加上排他锁后,该表就不能再被加表锁。数据库程序如何知道该表不能被加表锁?一种方式是逐条的判断该
表的每一条记录是否已经有排他锁,另一种方式是直接在表这一层级检查表本身是否有意向锁,不需要逐条判断。显然后者效率高。
更新锁
为解决死锁,引入更新锁
更新锁的意思是:“我现在只想读,你们别人也可以读,但我将来可能会做更新操作,我已经获取了从共享锁(用来读)到排他锁
(用来更新)的资格”。一个事物只能有一个更新锁获此资格。
共享锁和更新锁可以同时在同一个资源上。这被称为共享锁和更新锁是兼容的
计划锁(Schema Locks) :DDL语句都会加Sch-M锁
该锁不允许任何其它session连接该表。连都连不了这个表了,当然更不用说想对该表执行什么sql语句了。
如何加锁,何时加锁,加什么锁,你可以通过hint手工强行指定,但大多是数据库系统自动决定的。这就是为什么我们可以不懂锁也可
以高高兴兴的写SQL。
锁的粒度就是指锁的生效范围,就是说是行锁,还是页锁,还是整表锁. 锁的粒度同样既可以由数据库自动管理,也可以通过手工指定hint来管理
如何提高并发效率
悲观锁:利用数据库本身的锁机制实现。通过上面对数据库锁的了解,可以根据具体业务情况综合使用事务隔离级别与合理的手工指定锁的方式比如降低锁的粒度等减少并发等待。
乐观锁:利用程序处理并发。原理都比较好理解,基本一看即懂。方式大概有以下3种
对记录加版本号.
对记录加时间戳.
对将要更新的数据进行提前读取、事后对比
封锁、时间戳、乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段
当并发事务同时访问一个资源时,有可能导致数据不一致,因此需要一种机制来将数据访问顺序化,以保证数据库数据的一致性。锁就是其中的一种机制。
锁的分类(oracle)
一、按操作划分,可分为DML锁、DDL锁
二、按锁的粒度划分,可分为表级锁、行级锁、页级锁(MySQL)
三、按锁级别划分,可分为共享锁又称读锁、排他锁又称写锁
四、按加锁方式划分,可分为自动锁、显示锁
五、按使用方式划分,可分为乐观锁、悲观锁
DML锁(data locks,数据锁),用于保护数据的完整性,其中包括行级锁(Row Locks (TX锁))、表级锁(table lock(TM锁))。 DDL锁(dictionary locks,数据字典锁),用于保护数据库对象的结构,如表、索引等的结构定义。其中包排他DDL锁(Exclusive DDL lock)、共享DDL锁(Share DDL lock)、可中断解析锁(Breakable parse locks)
获准排他锁的事务既能读数据,又能修改数据。
用法:
SELECT ... FOR UPDATE;
在查询语句后面增加FOR UPDATE,Mysql会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。
共享锁用法:
SELECT ... LOCK IN SHARE MODE;
悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度(悲观),因此,在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)
在数据库中,悲观锁的流程如下:
在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。 具体响应方式由开发者根据实际需要决定。
如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。
数据版本,为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。
实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳。
锁
最新推荐文章于 2021-06-27 11:14:31 发布