数据库锁简单了解

共享锁(Shared lock)。 例1:----------------------------------------T1: select * from table (请想象它需要执行1个小时之久,后面的sql语句请都这么想象)T2: update table set column1='hello'过程:T1运行 (加共享锁)T2运行If T1 还没执行完 T2等......else 锁被释放 T2执行endifT2之所以要等,是因为T2在执行update前,试图对table表加一个排他锁,而数据库规定同一资源上不能同时共存共享锁和排他锁。所以T2必须等T1执行完,释放了共享锁,才能加上排他锁,然后才能开始执行update语句。

例2:----------------------------------------T1: select * from tableT2: select * from table这里T2不用等待T1执行完,而是可以马上执行。分析:T1运行,则table被加锁,比如叫lockAT2运行,再对table加一个共享锁,比如叫lockB。两个锁是可以同时存在于同一资源上的(比如同一个表上)。这被称为共享锁与共享锁兼容。这意味着共享锁不阻止其它session同时读资源,但阻止其它session update

例3:----------------------------------------T1: select * from tableT2: select * from tableT3: update table set column1='hello'这次,T2不用等T1运行完就能运行,T3却要等T1和T2都运行完才能运行。因为T3必须等T1和T2的共享锁全部释放才能进行加排他锁然后执行update操作。

例4:(死锁的发生)----------------------------------------T1:begin transelect * from table (holdlock) (holdlock意思是加共享锁,直到事物结束才释放)update table set column1='hello'T2:begin transelect * from table(holdlock)update table set column1='world'假设T1和T2同时达到select,T1对table加共享锁,T2也对加共享锁,当T1的select执行完,准备执行update时,根据锁机制,T1的共享锁需要升级到排他锁才能执行接下来的update.在升级排他锁前,必须等table上的其它共享锁释放,但因为holdlock这样的共享锁只有等事务结束后才释放,所以因为T2的共享锁不释放而导致T1等(等T2释放共享锁,自己好升级成排他锁),同理,也因为T1的共享锁不释放而导致T2等。死锁产生了。---------事务未结束不释放锁,互相再等对方释放锁

例5-----------------------------更新锁(Update lock) 为解决死锁,引入更新锁。---------------------------------------T1:begin transelect * from table(updlock) (加更新锁)update table set column1='hello'T2:begin transelect * from table(updlock)update table set column1='world'更新锁的意思是:“我现在只想读,你们别人也可以读,但我将来可能会做更新操作,我已经获取了从共享锁(用来读)到排他锁(用来更新)的资格”。一个事物只能有一个更新锁获此资格。T1执行select,加更新锁。T2运行,准备加更新锁,但发现已经有一个更新锁在那儿了,只好等。当后来有user3、user4...需要查询table表中的数据时,并不会因为T1的select在执行就被阻塞,照样能查询

例6----------------------------------------------------------T1: select * from table(updlock) (加更新锁)T2: select * from table(updlock) (等待,直到T1释放更新锁,因为同一时间不能在同一资源上有两个更新锁)T3: select * from table (加共享锁,但不用等updlock释放,就可以读)这个例子是说明:共享锁和更新锁可以同时在同一个资源上。这被称为共享锁和更新锁是兼容的

例7----------------------------------------alter table .... (加schema locks,称之为Schema modification (Sch-M) locksDDL语句都会加Sch-M锁该锁不允许任何其它session连接该表。连都连不了这个表了,当然更不用说想对该表执行什么sql语句了。

在只有单一用户的数据库中,用户可以任意修改数据,而无需考虑同时有其他用户正在修改相同的数据。但在一个多用户数据库中,多个并发事 务中包含的语句可能 会修改相同的数据。数据库中并发执行的事务最终应产生有意义且具备一致性的结果。因此在多用户数据库中,对数据并发访问(data concurrency)及数据一致性(data consistency)进行控制是两项极为重要的工作。

1、数据并发访问指多用户同时访问相同的数据。

2、数据一致性指系统中每个用户都能够取得具备一致性的数据,同时还能够看到自己或其他用户所提交的事务对数据的修改。

为了描述同时执行的多个事务如何实现数据一致性,数据库研究人员定义了被称为串行化处理(serializability)的事务隔离 模型(transaction isolation model)。当所有事务都采取串行化的模式执行时,我们可以认为同一时间只有一个事务在运行(串行的),而非并发的。

以串行化模式对事务进行隔离的效果很好,但在此种模式下应用程序的效率将大大降低。将并行执行的事务完全隔离意味着即便当前只存在一个 对表进行查询(query)的事务,其他事务也不能再对此表进行插入(insert)操作了。总之,为了满足实际要求,我们需要在事务的隔离程度与应用的 性能之间找出一个平衡点。

ANSI/ISO SQL 标准(SQL92)定义了四种事务隔离级别(transaction isolation level),这四种隔离级别所能提供的事务处理能力各不相同。这些事务隔离级别是针对三种现象定义的,在并发事务执行时,需要阻止这三种现象 中的一种或多种发生。

三种需要阻止的现象(preventable phenomena)是:

1、脏读取(dirty read):一个事务读取了被其他事务写入但还未提交的数据。

2、不可重复读取(nonrepeatable read):一个事务再次读取其之前曾经读取过的数据时,发现数据已被其他已提交的事务修改或删除。

3、不存在读取(phantom read):事务按照之前的条件重新查询时,返回的结果集中包含其他已提交事务插入的满足条件的新数据。

oracle中针对管理数据并发访问及数据一致性,使用的多种方式中有一种程序代码可以参考的方式:

多版本并发访问控制

Oracle 能够自动地实现一个查询的读一致性,即一个查询所获得的数据来自同一时间点 在一个查询执行期间,只有在查询执行前提交的数据对此查询才是可见的。查询无法看到其开始执行后提交的数据。   Oracle 的串行化隔离适合于具备以下特点的系统:出现修改相同数据的事务的几率较小,且长时间执行的事务以只读操作为主。最适合采用串行化隔离的系统是大型数据库,且其中主要运行更新少量数据的短小事务。 在程序系统的日常操作中假如多数为查询并且更新和删除事务操作量小的话,完全可以使用oracle数据的串行化隔离级别,但是假如更新和删除事务操作量大的话最好还使用其他的事务隔离级别,再者,oracle的串行化隔离级别能够满足上面需求的系统,但是其他的一些数据库就估计够呛了,oracle针对串行化隔离级别做过多的处理。   串行化事务隔离级别除外,oracle还提供了其他类型的事务隔离级别:                                          脏读取       不可重复读取     不存在读取                                                                 未提交读取                       允许              允许                  允许
已提交读取                       不允许              允许               允许
可重复读取                       不允许               不允许           允许
    已提交读取 Oracle 默认使用的事务隔离级别。事务内执行的查询只能看到查询执行前(而非事务开始前)就已经提交的数据。Oracle 的查询永远不会读取脏数据(未提交的数据)。

猜你喜欢

转载自liuzhiqiang19890403.iteye.com/blog/2170460