关于并发控制

 

什么是并发控制?

当许多人试图同时修改数据库中的数据时,必须实现一个控制系统,使一个人所做的修改不会对他人所做的修改产生负面影响。这称为并发控制。

简单的理解就是2个或多个用者同时编辑相同的数据。这里的用者可能是:实际用户、不同服务、不同的代码段(使用多线程),及其在断开式和连接式情况下可能发生的情况。

并发控制理论根据建立并发控制的方法而分为两类:

悲观并发控制(Pessimistic Concurrency)

一个锁定系统,可以阻止用户以影响其他用户的方式修改数据。如果用户执行的操作导致应用了某个锁,只有这个锁的所有者释放该锁,其他用户才能执行与 该锁冲突的操作。这种方法之所以称为悲观并发控制,是因为它主要用于数据争用激烈的环境中,以及发生并发冲突时用锁保护数据的成本低于回滚事务的成本的环 境中。

简单的理解通常通过“独占锁”的方法。获取锁来阻塞对于别的进程正在使用的数据的访问。换句话说,读者和写者之间是会互相阻塞的 ,这可能导致数据同步冲突。

乐观并发控制(Optimistic Concurrency)

在乐观并发控制中,用户读取数据时不锁定数据。当一个用户更新数据时,系统将进行检查,查看该用户读取数据后其他用户是否又更改了该数据。如果其他 用户更新了数据,将产生一个错误。一般情况下,收到错误信息的用户将回滚事务并重新开始。这种方法之所以称为乐观并发控制,是由于它主要在以下环境中使 用:数据争用不大且偶尔回滚事务的成本低于读取数据时锁定数据的成本。

 

 

 

 

 

 

SQL server锁的机制

SQL server的所有活动都会产生锁。锁定的单元越小,就越能越能提高并发处理能力,但是管理锁的开销越大。如何找到平衡点,使并发性和性能都可接受是SQL Server的难点。
SQL Server有如下几种琐:
1、 共享锁
用于只读操作(SELECT),锁定共享的资源。共享锁不会阻止其他用户读,但是阻止其他的用户写和修改。
2、 更新锁
更新锁是一种意图锁,当一个事物已经请求共享琐后并试图请求一个独占锁的时候发生更新琐。例如当两个事物在几行数据行上都使用了共享锁,并同时试图获取独占锁以执行更新操作时,就发生了死锁:都在等待对方释放共享锁而实现独占锁。更新锁的目的是只让一个事物获得更新锁,防止这种情况的发生。
3、 独占锁
一次只能有一个独占锁用在一个资源上,并且阻止其他所有的锁包括共享缩。写是独占锁,可以有效的防止’脏读’
4、 意图缩
在使用共享锁和独占锁之前,使用意图锁。从表的层次上查看意图锁,以判断事物能否获得共享锁和独占锁,提高了系统的性能,不需从爷或者行上检查。
5、 计划锁
Sch-M,Sch-S。对数据库结构改变时用Sch-M,对查询进行编译时用Sch-S。这两种锁不会阻塞任何事物锁,包括独占锁。

读是共享锁,写是排他锁,先读后更新的操作是更新锁,更新锁成功并且改变了数据时更新锁升级到排他锁。锁的类型有:
DB-----数据库,由于 dbid 列已包含数据库的数据库 ID,所以没有提供任何信息
FIL----文件
IDX----索引
PG-----页,数据或索引页。页码。页由 fileid:page 组合进行标识,其中,fileid 是 sysfiles 表中的 fileid,而 page 是该文件内的逻辑页码。
KEY----键,用于保护可串行事务中的键范围
TAB----表,包括所有数据和索引在内的整个表。由于 ObjId 列已包含表的对象 ID,所以没有提供任何信息
EXT----区域, 相邻的八个数据页或索引页构成的一组。正被锁定的扩展盘区中的第一个页码。页由 fileid:page 组合进行标识
RID----行,表内已锁定行的行标识符。行由 fileid:page:rid 组合进行标识,其中,rid 是页中的行标识符

锁的状态:
Grant---能使用被授权的资源
Wait----能使用被其他任务阻塞的资源
Cnvrt---Convert,锁正在被转换

细分锁的模式:
0 Null 没有得到资源的访问权限
1 Sch-S (Schema stability) 对查询进行编译时。能防止加锁的对象被删除直到解锁
2 Sch-M (Schema Modification) 改变数据库结构时发生。能防止其他的事物访问加锁的对象
3 IS (Intent Shares) 意图共享锁。
4 SIU(Share Intent Update) 意图在维护资源的共享锁时,把更新锁放到锁层次结构的下层资源上
5 IS-S(Intent Share-shared) 复合键范围锁
6 IX(Intent Exclusive) 意图排他锁
7 SIX(Share Intent Exclusive)
8 S(Share) 共享锁
9 U(Update) 更新锁。防止死锁
10 Iin-Nul(Intent Insert-Null) 索引行层次的锁定,复合键范围锁
11 IS-X(Intent Share-Exclusive)
12 IU(Intent Update) 意图更新锁
13 IS-U(Intent Share Update) 串行更新扫描
14 X(Exclusive) 排他锁
15 BU 块操作使用的锁

所以有如下的结论。

1、一个连接在修改数据块时别的连接不能修改这个数据块,直到解锁。
并行访问是任何数据库解决方案都最为重视的问题了,为了解决并行访问方面的问题各类数据库系统提出了各种各样的方案。SQL Server采用了多线程机制,它当然能够一次处理多个请求。不过,在用户修改数据的情况下并行访问问题就变得复杂起来了。显然,数据库通常只允许唯一用户一次修改特定的数据。当某一用户开始修改某块数据时, SQL Server能很快地锁定数据,阻止其他用户对这块数据进行更新,直到修改该数据的第一位用户完成其操作并提交交易或者回滚。但是,当某一位用户正在修改某块数据时假设另一位用户又正想查询该数据的信息时会发生什么情况呢?
2、通常情况下,一个连接在修改数据块时别的连接也不能查询这个数据块,直到解锁。反之亦然:读的时候不能写和修改。这个方案会降低系统的性能和效率,尽管现在是行级锁(7.0以前是锁页甚至是锁表),如果你一次修改多行数据,SQL Server则会把数据锁定范围提升到页级别乃至锁定整个数据表,从而不必针对每一记录跟踪和维护各自的数据锁,这样能加快修改的速度,消耗小的服务器资源,但是并发性就差了。。
3、一个连接写的时候,另一个连接可以写,但是不得读
4、多个连接可以同时读同一行。

所以锁发生在读、写的竞争上。

5、设置事物的级别 SET TRANSACTION ISOLATION LEVEL
A、READ COMMITTED :指定在读取数据时控制共享锁以避免脏读,但数据可在事务结束前更改,从而产生不可重复读取或幻像数据。该选项是 SQL Server 的默认值。
B、READ UNCOMMITTED:执行脏读或 0 级隔离锁定,这表示不发出共享锁,也不接受排它锁。当设置该选项时,可以对数据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出现在数据集中

本篇文章来源于 [教程学习网] 转载请以链接形式注明出处

 

 

 

 

关于oracle 锁机制锁问题的详细分析(处理锁定),以及死锁的解决方案
在任何多用户数据库应用中,最终必然会出现两个用户希望同时处理相同记录的情况.这种情况在逻辑上是不可能的,并且数据库必须确保其在物理上也是不可能的.事务隔离性原则要求数据库保证:在 ,这个会话无法影响另一个会话,并且后者也无法看到前者.为了实现这个要求,数据库创行话并发的数据访问,甚至在多个会话请求访问相同的记录时,数据库也必须确保这些会话排队依次进行.
借助于记录和表锁定机制,我们可以实现并发的串行化.oracle数据库中的锁定是完全自动的.一般而言,只有在试图结合软件与自动锁定机制是或者编程人员编写的代码太糟糕时才会引发某些问题.


                                                 共享锁与排他锁
 
oracle数据库中锁定的标准级别保证了最大可能的并发级别也就是说,如果某个会话正在更新一条记录,那么只有这条记录会被锁定.此外,锁定这条记录是为了防止其他会话对其进行更新,其他会话可以随时执行读取操作.只有在使用commit或rollback命令结束事务之后,锁定才会被解除.这种锁定是一个”排他锁”:在指定记录上请求排他锁的第一个会话会得到这个锁定,其他请求对该记录进行写访问的会话则必须等待.虽然这条记录已通过锁定会话进行了更新,但是对其进行读访问你是被允许的(而且经常会出现这种情况),并且这些读操作会涉及撤销数据的使用,从而确保都会回并不会看到任何未被提交的变化
对于一条记录或一个完整表上的一个排他锁来说,每次只能有一个会话可以获得这个排他锁,不过许多会话可以同时获得相同对象上的”共享锁”.在一条记录上设置共享锁毫无意义,其原因在于锁定一条记录的唯一目的就是不允许其他会话更改它.共享锁被置于整个表上,同时许多会话可以获得同一个表上的共享锁.在一个表上放置共享锁的目的是为了防止另一个会话获得这个表上的排他锁(在已存在共享锁的情况下无法再获得排他锁).在表上防止排他锁是需要执行DDL语句.如果其他任何会话已经在一个表上放置了共享锁,那么我们就无法执行修改某个对象的语句(例如删除这个表的某一列).
为了在记录上执行DML语句,当前会话必须获取待更新记录上的排他锁以及包含这些记录的表上的共享锁.如果另一个会话已经获取了待更新记录上的排他锁,那么当前会话将被挂起,直至使用COMMIT或ROLLBACK命令解除这些锁定,如果另一个会话已经获取了待修改记录的表上的共享锁以及其他记录上的排他锁,那么就不存在任何问题.一个表上的排他锁会锁定这个表,但是,如果不需要执行DDL语句,那么我们就可以不锁定整个表的默认锁定机制.
 
提示:
只有在特别请求并且编程人员具有充分理由的情况下,才可以要求在整个表上放置排他锁.

 

 
DML锁与DDL锁
所有DML语句都至少需要两种锁定:受影响记录上的排他锁,以及包含受影响记录的表上的共享锁.排他锁能够防止其他会话干预指定的记录,而共享锁则能够阻止其他会话使用DDL语句修改表的定义.这两种锁定会被自动请求.如果某条DML语句在指定记录上无法获取所需的排他锁,那么这条语句会被挂起直至获得所需的排他锁.
执行DDL命令需要使用所涉及对象上的排他锁.只有在针对指定表的所有DML事务结束,并且记录上的排他锁以及表上的共享锁都被解除之后,我们才可以获得执行DDL命令所需的排他锁,任何DDL语句所需的排他锁都是被自动请求的.但是,如果无法获取所需的排他锁(通常是因为其他会话已经获得用于DML语句的共享锁),那么DDL语句就会由于错误立即终止.
 
为了更好的说明锁机制,我们还是看一个世纪的例子吧:
1.       使用SQL*PLUS,作为用户SYSTEM连接数据库.
2.       创建一个表,并且在这个表中插入一条记录.
>create table t1(c1 number);
       >insert into t1 values(1);
       >commit;
3.再次使用SQL*PLUS并作为用户SYSTEM进行连接,从而打开另一个会话.
4.在第一个会话中执行一个DML命令,这个命令会在插入的记录上放置一个排他锁,同时还会在创建的表上放置一个共享锁.
   >update table t1 set c1=2 where c1=1;
5.如下所示,在第二个会话中执行第一条针对新建表的DDL语句.
   >alter table t1 add(c2 date);
   error at line 1:
ora-00054:resource busy and acquire with nowait specified
因为DDL语句需要表上的排他锁,而这与DML语句已在表上放置了共享锁相冲突,所以试图在表中插入一个列的这条DDL语句会失败.需要注意的是:在类似情况下,DML语句会等待并不断进行尝试,直至获得其所需的锁(换句话说就是挂起);而DDL语句则会由于错误立即终止.
       6.在第一个会话中,提交当前事务
          >commit;
       7.在第二个会话中,重新执行步骤5.此时,因为不纯在与DDL排他锁相冲突的DML共享锁,因此DDL语句将成功的执行.
       8.在第一个会话中 ,锁定整个表.
        >lock table t1 in exclusive mode;
       9.在第二个会话中,插入一条记录.此时,这个会话将被挂起.
        >insert into t1 values (1,sysdate);
       10.在第一个会话中,通过执行COMMIT命令解除整个表上的锁定.需要注意的是,ROLLBACK命令也可以实现相同的目的.
        >commit;
       11.第二个会话会释放并且现在会完成插入操作.随后,执行COMMIT命令,终止当前事务斌且解除该记录上的排他锁.

关于如何解决死锁的问题.

1.查哪个过程被锁
查V$DB_OBJECT_CACHE视图:


SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER=''过程的所属用户'' AND LOCKS!=''0'';

2. 查是哪一个SID,通过SID可知道是哪个SESSION.
查V$ACCESS视图:


SELECT * FROM V$ACCESS WHERE OWNER=''过程的所属用户'' AND NAME=''刚才查到的过程名'';

3. 查出SID和SERIAL#
查V$SESSION视图:


SELECT SID,SERIAL#,PADDR FROM V$SESSION WHERE SID=''刚才查到的SID''

查V$PROCESS视图:


SELECT SPID FROM V$PROCESS WHERE ADDR=''刚才查到的PADDR'';

4. 杀进程
(1).先杀ORACLE进程:


ALTER SYSTEM KILL SESSION ''查出的SID,查出的SERIAL#'';

(2).再杀操作系统进程:


KILL -9 刚才查出的SPID

ORAKILL 刚才查出的SID 刚才查出的SPID
文章出处:DIY部落

 

 

 

 

 

 

 

 

 

 

 

 

关于锁的解决方案:

 

.net的解决方案

 

大多数据库自身都有很好的迸发处理机制,程序中你只要用事务处理来保证数据的一致性和完整性即可....

 

MS-SQL Server 使用以下资源锁模式。

锁模式 描述
共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
更新 (U) 用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。
排它 (X) 用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。
意向锁 用于建立锁的层次结构。意向锁的类型为:意向共享 (IS)、意向排它 (IX) 以及与意向排它共享 (SIX)。
架构锁 在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改 (Sch-M) 和架构稳定性 (Sch-S)。
大容量更新 (BU) 向表中大容量复制数据并指定了 TABLOCK 提示时使用。

 

 

用事物处理锁的问题

 

public void ExeSqls(string theSql)
        {
           
using (SqlCommand theCommand2 = new SqlCommand())
            {
                theConn.Open();
                SqlTransaction trans
= theConn.BeginTransaction(IsolationLevel.ReadCommitted);
               
try
                {
                    theCommand2.Connection
= theConn;
                    theCommand2.Transaction
= trans;
                    theCommand2.CommandText
= theSql;
                    theCommand2.ExecuteNonQuery();
                    trans.Commit();
                  
                }
               
catch (Exception ex)
                {
                    trans.Rollback();
                   
throw new ApplicationException(ex.Message);
                }
               
finally
                {
                    theConn.Close();
                }
            }
        }

 

也可以用lock关键字来挂起当前线程等

 

lock

{

    ......

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值