数据库锁总结

http://www.cnblogs.com/ismallboy/p/5574006.html

数据库锁出现的原因是为了处理并发问题,因为数据库是一个多用户共享的资源,当出现并发的时候,就会导致出现各种各样奇怪的问题,就像程序代码一样,出现多线程并发的时候,如果不做特殊控制的话,就会出现意外的事情,比如“脏“数据、修改丢失等问题。所以数据库并发需要使用事务来控制,事务并发问题需要数据库锁来控制,所以数据库锁是跟并发控制和事务联系在一起的。

  平时会经常看到或者听到数据库锁有“共享锁”,“排它锁”,“互斥锁”,“写锁”,“读锁”,“悲观锁”,“乐观锁”,“行级锁”,“表级锁”,“页级锁”等,同时我们还会常看到“丢失修改“,”不可重复读“,”读脏数据“这三个术语,他们究竟是什么关系以及怎么理解呢,下面就来介绍一下他们。

  先说事务的特性,要想成为事务,必须满足:ACID(原子性,一致性,隔离性,持久性)四特性,事务是恢复和并发控制的基本单位。原子性指的是事务是数据库的逻辑工作单位,事务中操作要么都做,要么都不做;一致性指的是事务的执行结果必须是使数据库从一个一致性状态变大另一个一致性状态,一致性和原子性是密切相关的;隔离性指的是一个事务执行不能被其他事务干扰;持久性指的是一个事务一旦提交,他对数据库中数据的改变就是永久性的。

  先说悲观锁和乐观锁吧。并发控制一般采用三种方法,分别是乐观锁和悲观锁以及时间戳。乐观锁认为一个用户读数据的时候,别人不会去写自己所读的数据;悲观锁就刚好相反,觉得自己读数据库的时候,别人可能刚好在写自己刚读的数据,其实就是持一种比较保守的态度;时间戳就是不加锁,通过时间戳来控制并发出现的问题。悲观锁就是在读取数据的时候,为了不让别人修改自己读取的数据,就会先对自己读取的数据加锁,只有自己把数据读完了,才允许别人修改那部分数据,或者反过来说,就是自己修改某条数据的时候,不允许别人读取该数据,只有等自己的整个事务提交了,才释放自己加上的锁,才允许其他用户访问那部分数据。乐观锁就比较简单了,就是不做控制,这只是一部分人对于并发所持有的一种态度而已。时间戳就是在数据库表中单独加一列时间戳,比如“TimeStamp”,每次读出来的时候,把该字段也读出来,当写回去的时候,把该字段加1,提交之前 ,跟数据库的该字段比较一次,如果比数据库的值大的话,就允许保存,否则不允许保存,这种处理方法虽然不使用数据库系统提供的锁机制,但是这种方法可以大大提高数据库处理的并发量,因为这种方法可以避免了长事务中的数据库加锁开销(操作员A 和操作员B操作过程中,都没有对数据库数据加锁),大大提升了大并发量下的系 统整体性能表现。 需要注意的是,乐观锁机制往往基于系统中的数据存储逻辑,因此也具备一定的局 限性,如在上例中,由于乐观锁机制是在我们的系统中实现,来自外部系统的用户 余额更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。在 系统设计阶段,我们应该充分考虑到这些情况出现的可能性,并进行相应调整(如 将乐观锁策略在数据库存储过程中实现,对外只开放基于此存储过程的数据更新途 径,而不是将数据库表直接对外公开)。以上悲观锁所说的加“锁”,其实分为几种锁,分别是:排它锁和共享锁,其中排它锁又称为写锁,共享锁又称为读锁。(ps.可以参考此文 “http://blog.sina.com.cn/s/blog_548bd2090100ir7k.html”)

  共享锁和排它锁是具体的锁,是数据库机制上的锁,存在以下关系:

  

      (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,这样就会导致死锁,死锁这种没有完全解决的方法,只能尽量预防,预防的方法有:①一次封锁发,指的是一次性把所需要的数据全部封锁住,但是这样会扩大了封锁的范围,降低系统的并发度;②顺序封锁发,指的是事先对数据对象指定一个封锁顺序,要对数据进行封锁,只能按照规定的顺序来封锁,但是这个一般不大可能的。另外,系统如何判断出现死锁呢,毕竟出现死锁不能一直干等下去,要及时发现死锁同时尽快解决出现的死锁,诊断和判断死锁有两种方法,一是超时法,二是等待图法。超时法就是如果某个事物的等待时间超过指定时限,则判定为出现死锁;等待图法指的是如果事务等待图中出现了回路,则判断出现了死锁。对于解决死锁的方法,只能是撤销一个处理死锁代价最小的事务,释放此事务持有的所有锁,同时对撤销的事务所执行的数据修改操作必须加以恢复。

  最后,说下行级锁和表级锁。(一下摘自:http://blog.sina.com.cn/s/blog_548bd2090100ir7k.html

锁包括行级锁和表级锁

行级锁是一种排他锁,防止其他事务修改此行;在使用以下语句时,Oracle会自动应用行级锁:
INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT];
SELECT … FOR UPDATE语句允许用户一次锁定多条记录进行更新
使用COMMIT或ROLLBACK语句释放锁

表级锁又分为5类:

行共享 (ROW SHARE) – 禁止排他锁定表
行排他(ROW EXCLUSIVE) – 禁止使用排他锁和共享锁
共享锁(SHARE) - 锁定表,对记录只读不写,多个用户可以同时在同一个表上应用此锁
共享行排他(SHARE ROW EXCLUSIVE) – 比共享锁更多的限制,禁止使用共享锁及更高的锁
排他(EXCLUSIVE) – 限制最强的表锁,仅允许其他用户查询该表的行。禁止修改和锁定表。

时间: 2024-10-13 21:18:24

数据库锁总结的相关文章

【转】数据库锁机制

1 前言 数据库大并发操作要考虑死锁和锁的性能问题.看到网上大多语焉不详(尤其更新锁),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一个线程,T2 为另一个线程.T3,T4以此类推.下面以SQL Server(2005)为例. 2 锁的种类 共享锁(Shared lock). 例1: ---------------------------------------- T1: select * from table (请想象它需要执行

数据库锁的基本原理

数据库锁的基本原理 为了保证数据的完事性和一致性,数据库系统采用锁来实现事务的隔离性.各种大型数据库采用的锁基本理论是一致的,但在具体实现上各有差别. 从并发事务锁定的关系上看,可以分为共享锁定和独占锁定.从锁定的对象不同,一般可以分为表锁定和行锁定. 锁 共享锁用于读取数据操作,它是非独占的,允许其他事务同时读取其锁定的资源,但不允许其他事务更新它. 独占锁也叫排他锁,适用于修改数据的场合.它所锁定的资源,其他事务不能读取也不能修改. 当一个事务访问某种数据库资源时,如果执行select语句,

ABAP锁、数据库锁

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4293533.html ABAP数据锁定... 338 SM12锁查看与维护... 344 通用加锁与解锁函数... 344 ABAP程序锁定... 345 数据库锁... 347 锁的分类和兼容性... 347 并发性与锁的权衡... 34

数据库锁机制

1 前言 数据库大并发操作要考虑死锁和锁的性能问题.看到网上大多语焉不详(尤其更新锁),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一个线程,T2 为另一个线程.T3,T4以此类推.下面以SQL Server(2005)为例. 2 锁的种类 共享锁(Shared lock). 例1: ---------------------------------------- T1: select * from table (请想象它需要执行

数据库锁之乐观锁

一.乐观锁的介绍 乐观锁是相对悲观锁而言,也是为了避免数据库幻读.业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性. 乐观锁的机制:对每条数据库加上版本号或时间撮,在每次对数据进行操作(尤其是修改操作)时,总会带上版本号获取数据同时更改后修改版本号. 二.乐观锁的代码示例 2.1 创建一张表 create table em_oplock ( id VARCHAR(100) not null, value VARCHAR(

基于Oracle数据库锁机制,解决集群中的并发访问问题

1.需求 应用场景是这样的: 使用Oracle数据保存待办任务,使用状态字段区分任务是否已经被执行.多个Worker线程同时执行任务,执行成功或失败后,修改状态字段的值. 假设数据库表结构如下所示. create table Task( id varchar2(32), name varchar2(32), flag varchar2(1), worker varchar2(32) ); flag 可取的值包括:0-待办,1-已办,-1-失败待重试. 需要避免的问题: 多个Worker同时工作时

数据库“锁”事一例

在做的一个账单计息功能,其中,账单表的主键是BillId,varchar类型,BillId取值形如B0000001,生成规则是每次新增记录是先从账单表里计算出最大的BillId数字,然后+1再转换后作为新增记录的BillId.例如,B0000001.B0000002. 逻辑很简单,但考虑到并发,技术上就要费点心了. 为了简化场景,这里我写了一些测试用例,涉及到一个包含两个字段的表student(id int, sno varchar(32)),PK是id.数据库是引擎为InnoDB的Mysql5

数据库锁简析(转载)

一.前言 数据库大并发操作要考虑死锁和锁的性能问题.这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一个线程,T2 为另一个线程.T3,T4以此类推.下面以SQL Server为例. 二.锁的种类 共享锁(Shared lock). 例1: ---------------------------------------- T1: select * from table (请想象它需要执行1个小时之久,后面的sql语句请都这么想象) T2:

数据库锁的粒度

所谓粒度,即细化的程度.锁的粒度越大,则并发性越低且开销大:锁的粒度越小,则并发性高且开销小. 锁的粒度主要有下面几种类型: (1)行锁,行锁是粒度中最小的资源.行锁就是指事务在操作数据的过程中,锁定一行或多行的数据,其它事务不能同一时候处理这些行的数据.行级锁占用的数据资源最小,所以在事务的处理过程中,同意其它事务操作同一表的其它数据. (2)页锁,一次锁定一页.25个行锁可升级为一个页锁. (3)表锁,锁定整个表.当整个数据表被锁定后,其它事务就不可以使用此表中的其它数据.使用表锁可以使事务