数据库事务隔离级别与锁

一,事务的4个基本特征

Atomic(原子性):
事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要
么全部成功,要么全部失败。

Consistency(一致性):
只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初
状态。

Isolation(隔离性):
事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正
确性和完整性。同时,并行事务的修改必须与其他并行事务的修改
相互独立。

Durability(持久性):
事务结束后,事务处理的结果必须能够得到固化。

以上属于废话

二,为什么需要对事务并发控制

如果不对事务进行并发控制,我们看看数据库并发操作是会有那些异常情形

更新丢失Lost update:
两个事务都同时更新一行数据,但是第二个事务却中途失败退出,
导致对数据的两个修改都失效了。

脏读Dirty Reads:
一个事务开始读取了某行数据,但是另外一个事务已经更新了此数
据但没有能够及时提交。这是相当危险的,因为很可能所有的操作
都被回滚。

不可重复读Non-repeatable Reads:
一个事务对同一行数据重复读取两次,但是却得到了不同的结果。

二次更新问题Second lost updates problem:
无法重复读取的特例。有两个并发事务同时读取同一行数据,然后其
中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成
第一次写操作失效。

不可重复读Phantom Reads:
事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查
询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是
因为在两次查询过程中有另外一个事务插入数据造成的。

三, 数据库的隔离级别

为了兼顾并发效率和异常控制,在标准SQL规范中,定义了4个事务隔
离级别,(ORACLE和SQLSERER对标准隔离级别有不同的实现 )

事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了所使用的锁定行为:

Read Uncommitted:
直译就是"读未提交",意思就是即使一个更新语句没有提交,但是别
的事务可以读到这个改变.这是很不安全的.

Read Committed:
直译就是"读提交",意思就是语句提交以后即执行了COMMIT以后
别的事务就能读到这个改变.

Repeatable Read:
直译就是"可以重复读",这是说在同一个事务里面先后执行同一个
查询语句的时候,得到的结果是一样的.

Serializable:
直译就是"序列化",意思是说这个事务执行的时候不允许别的事务
并发执行.

四,隔离级别对并发的控制


下表是各隔离级别对各种异常的控制能力。

 LUDRNRRSLUPR
RUYYYYY
RCNNYYY
RRNNNNY
SNNNNN

 

 

 

 

 

 

 

 

 

(注:LU:丢失更新;DR:脏读;NRR:非重复读;SLU:二类丢失更新;PR:幻像读)

顺便举一小例。

MS_SQL:
--事务一
set transaction isolation level serializable
begin tran
insert into test values('xxx')

--事务二
set transaction isolation level read committed
begin tran
select * from test

--事务三
set transaction isolation level read uncommitted
begin tran
select * from test

在查询分析器中执行事务一后,分别执行事务二,和三。结果是事务二会等待,而事务三则会执行。

ORACLE:
--事务一
set transaction isolation level serializable;
insert into test values('xxx');
select * from test;

--事务二
set transaction isolation level read committed--ORACLE默认级别
select * from test

执行事务一后,执行事务二。结果是事务二只读出原有的数据,无视事务一的插入操作。

读者是否发现MS_SQL和ORACLE对并发控制的处理有所不同呢?

五,锁

下表是锁的兼容或冲突情形。

 现有SUX
申请    
S YYN
U YNN
X NNN

 

 

 

 

 

 

 

 

 

oracle:

 

  

 

六,隔离级别与锁

隔离级别越高越能保证数据完整性和一致性,但是对并发性能影响也越大。对于多数应用程序,可以优先考虑把数据库系统隔离级别设为Read Committed ,它能够避免脏读取而且具有较好并发性能。尽管它会导致不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制 。

锁(Lock) 是在多用户环境下对资源访问的一种限制。机制当对一个数据源加锁后,此数据源就有了一定的访问限制。我们就称对此数据源进行了“锁定”。在SQL Server中,可以对以下的对象进行锁定:

数据行(Row):数据页中的单行数据;
索引行(Key):索引页中的单行数据,即索引的键值;
页(Page):页是SQL Server 存取数据的基本单位,其大小为8KB;
盘区(Extent):一个盘区由8 个连续的页组成;
表(Table);
数据库(Database)。


在SQL Server 中,锁有两种分类方法。
(1) 从数据库系统的角度来看
锁分为以下三种类型:

1.独占锁(Exclusive Lock)
独占锁锁定的资源只允许进行锁定操作的程序使用,其它任何对它的操作均不会被接受。执行数据更新命令,即INSERT、 UPDATE 或DELETE 命令时,SQL Server 会自动使用独占锁。但当对象上有其它锁存在时,无法对其加独占锁。独占锁一直到事务结束才能被释放。
2.共享锁(Shared Lock)
共享锁锁定的资源可以被其它用户读取,但其它用户不能修改它。在SELECT 命令执行时,SQL Server 通常会对对象进行共享锁锁定。通常加共享锁的数据页被读取完毕后,共享锁就会立即被释放。
3.更新锁(Update Lock)
更新锁是为了防止死锁而设立的。当SQL Server 准备更新数据时,它首先对数据对象作更新锁锁定,这样数据将不能被修改,但可以读取。等到SQL Server 确定要进行更新数据操作时,它会自动将更新锁换为独占锁。但当对象上有其它锁存在时,无法对其作更新锁锁定。

 

2)从程序员的角度看
锁分为以下两种类型:

1.乐观锁(Optimistic Lock)

乐观锁对数据库系统的自动管理不感冒,需要程序员直接管理数据或对象上的加锁处理,并负责获取、共享和放弃正在使用的数据上的任何锁。

 

2.悲观锁(Pessimistic Lock)
悲观锁假定在处理数据时,不需要在应用程序的代码中做任何事情就可以直接在记录上加锁、即完全依靠数据库来管理锁的工作。一般情况下,当执行事务处理时SQL Server会自动对事务处理范围内更新到的表做锁定。

 

 

锁定优化程序提示及其描述
优化程序提示 优化程序提示描述
holdlock 保持锁定直到事务结束
nolock 检索数据时不使用锁
paglock 使用页面锁
tablock 使用表锁
tablockx 使用独占表锁
updlock 使用更新锁

如: SELECT *    FROM authors (paglock holdlock index=aunmind)  

 

 

死锁及其防止:

死锁(Deadlocking) 是在多用户或多进程状况下,为使用同一资源而产生的无法解决的争用状态,通俗地讲,就是两个用户各占用一个资源,两人都想使用对方的资源,但同时又不愿放弃自己的资源,就一直等待对方放弃资源,如果不进行外部干涉,就将一直耗下去。

死锁会造成资源的大量浪费,甚至会使系统崩溃。在SQL Server 中解决死锁的原则是“牺牲一个比两个都死强”,即挑出一个进程作为牺牲者,将其事务回滚,并向执行此进程的程序发送编号为1205 的错误信息。而防止死锁的途径就是不能让满足死锁条件的情况发生,为此,用户需要遵循以下原则:

尽量避免并发地执行涉及到修改数据的语句;
要求每个事务一次就将所有要使用的数据全部加锁,否则就不予执行;
预先规定一个封锁顺序所有的事务,都必须按这个顺序对数据执行封锁,例如,不同的过程在事务内部对对象的更新执行顺序应尽量保持一致;
每个事务的执行时间不可太长,对程序段长的事务可考虑将其分割为几个事务。

七,注意点

 

一般处理并发问题时的步骤:

1、开启事务。

2、申请写权限,也就是给对象(表或记录)加锁。

3、假如失败,则结束事务,过一会重试。

4、假如成功,也就是给对象加锁成功,防止其他用户再用同样的方式打开。

5、进行编辑操作。

6、写入所进行的编辑结果。

7、假如写入成功,则提交事务,完成操作。

8、假如写入失败,则回滚事务,取消提交。

9、(7.8)两步操作已释放了锁定的对象,恢复到操作前的状态。

 

对多表的操作最好一起取得锁,或则保证处理顺序;个人感觉还是前者好,虽然效率低一些


八,附
查看锁
ORACLE:
select object_name,session_id,os_user_name,oracle_username,process,locked_mode,status
from v$locked_object l, all_objects a
where l.object_id=a.object_id;

MS_SQL:EXEC SP_LOCK

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值