分享

数据库事务

 昵称299585 2009-09-13

一、数据库事务
1
、事务是作为单个逻辑工作单元执行的一系列操作。可以是一条SQL语句也可以是多条SQL语句。

2
、事务具有四个特性
  
原子性:不可分隔、成则具成、败则具败。
  
恢滦裕菏挛裨谕瓿墒保 匦胧顾 械氖 荻急3忠恢伦刺?
  
隔离性:独立的执行互不干扰。由并发事务所作的修改必须与任何其他并发事务所作的修改隔离(另外的描述:多个事务同时进行,它们之间应该互不干扰.应该防止一个事务处理其他事务也要修改的数据时,不合理的存取和不完整的读取数据)
  
3
、启动事务:使用 API 函数和 Transact-SQL 语句,可以按显式、自动提交或隐式的方式来启动事务。

4
、结束事务:您可以使用 COMMIT(成功) 或 ROLLBACK(失败) 语句,或者通过 API 函数来结束事务。

5
、创建事务的原则:
  
尽可能使事务保持简短很重要,当事务启动后,数据库管理系统 (DBMS) 必须在事务结束之前保留很多资源、以保证事务的正确安全执行。
  
特别是在大量并发的系统中, 保持事务简短以减少并发 资源锁定争夺,将先得更为重要。
   1
、事务处理,禁止与用户交互,在事务开始前完成用户输入。
   2
、在浏览数据时,尽量不要打开事务
   3
、尽可能使事务保持简短。
   4
、考虑为只读查询使用快照隔离,以减少阻塞。
   5
、灵活地使用更低的事务隔离级别。
   6
、灵活地使用更低的游标并发选项,例如开放式并发选项。
   7
、在事务中尽量使访问的数据量最小。

二、事务的隔离级别

1、数据库事务的隔离级别:四种

隔离级别

脏读(Dirty Read

不可重复读(NonRepeatable Read

幻读(Phantom Read

读未提交(Read uncommitted

可能

可能

可能

读已提交(Read committed

不可能

可能

可能

可重复读(Repeatable read

不可能

不可能

可能

可串行化(Serializable

不可能

不可能

不可能

2、数据库一般的默认隔离离级别是读已提交,默认的事务隔离级别下:Insertupdate delete下的是X, 会等待事务完成。通常情况下可以把隔离级别设为Read Commited,它能避免脏读,而且有较好的并发性能。尽管它会导致不可重复读、虚读和第二类更新丢失等问题,在可能出现这类问题的个别场合可以由应用程序釆用悲观锁或乐观锁来控制。


3
SQL语句可以使用SET TRANSACTION ISOLATION LEVEL来设置事务的隔离级别。如:SET TRANSACTION ISOLATION LEVEL   Read Committed。若要在应用程序中使用更严格或较宽松的隔离级别,可以通过使用   set transaction isolation level语句设置会话的隔离级别,来自定义整个会话的锁定。  
指定隔离级别后,sql server会话中所有select语句的锁定行为都运行于该隔离级别上,并一直保持有效直到会话终止或者将隔离级别设置为另一个级别。

4、另外要提一点:SQL标准对事务隔离级别的规定,是按该级别不可能发生什么问题来确定的,不一定会发生这样的问题;所以,不同的数据库对事务隔离的级别约定不一样,比如,有的数据库把 可重复读级别按可串行化来对待。(lkdlhw_2000个人理解:各个数据库应该都遵循四种标准的事务隔离等级的定义,但是某些数据库具体实现可能不存在四种,因为串行化可以避免不可重复读,因此某些数据库语法上支持设置事务隔离等级为不可重复读,但实际上是串行化在起作用。也就是说只要该级别能够避免不可重复读的问题,就可以称之为不可重复读取级别。)

5、该隔离级别定义一个事务必须与其他事务所进行的资源或数据更改相隔离的程度。事务隔离级别控制:
    
读取数据时是否占用锁以及所请求的锁类型。
    
占用读取锁的时间。
    
引用其他事务修改的行的读取操作是否:
    
在该行上的排他锁被释放之前阻塞其他事务。
    
检索在启动语句或事务时存在的行的已提交版本。
    
读取未提交的数据修改

三、锁

1、分类:从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁

2、事务使用锁,防止其他用户修改另外一个还没有完成的事务中的数据。对于多用户系统来说,锁机制是必须的。SQL Server有多种锁,允许事务锁定不同的资源。锁就是保护指定的资源,不被其他事务操作。SQL Server有多种锁,允许事务锁定不同的资源。锁就是保护指定的资源,不被其他事务操作。为了最小化锁的成本,SQL Server自动地以与任务相应等级的锁来锁定资源对象。锁定比较小的对象,例如锁定行,虽然可以提高并发性,但是却有较高的开支,因为如果锁定许多行,那么需要占有更多的锁。锁定比较大的对象,例如锁定表,会大大降低并发性,因为锁定整个表就限制了其他事务访问该表的其他部分,但是成本开支比较低,因为只需维护比较少的锁。

3、 锁的特点:
1.
锁是保证并发控制的手段
2.
可以锁定的资源包括行、页、簇、表和数据库
3.
锁的类型主要包括共享锁和排它锁
4.
特殊类型的锁包括意图锁、修改锁和模式锁
5.
共享锁允许其他事务继续使用锁定的资源
6.
排它锁只允许一个事务访问数据
7.
系统本身可以处理死锁
8.
用户可以根据实际情况定制锁的一些特征

4、锁是定义到sql语句上的,对数据进行操作的sql就是:selectInsertupdate delete。不同的事物隔离即被在执行sql的时候会向表上发送不同的锁。

关于锁的更多描述,可以去网上搜索一下。http://www./windows/sql/200604/1068.html

四、多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:

脏读dirty reads
  
当事务读取还未被提交的数据时,就会发生这种事件。举例来说:Transaction1修改了一行数据,然后Transaction2Transaction1还未提交修改操作之前读取了被修改的行。如果Transaction1回滚了修改操作,那么Transaction2读取的数据就可以看作是从未存在过的。
不可重复的读non-repeatable reads
  
当事务两次读取同一行数据,但每次得到的数据都不一样时,就会发生这种事件。举例来说:Transaction1读取一行数据,然后Transaction2修改或删除该行并提交修改操作。当Transaction1试图重新读取该行时,它就会得到不同的数据值(如果该行被更新)或发现该行不再存在(如果该行被删除)。    
虚读phantom read
  
如果符合搜索条件的一行数据在后面的读取操作中出现,但该行数据却不属于最初的数据,就会发生这种事件。举例来说Transactio1读取满足某种搜索条件的一些行,然后Transaction2插入了符合Transaction1的搜索条件的一个新行。如果Transaction1重新执行产生原来那些行的查询,就会得到不同的行。

为了解决这些问题,数据库引入了的机制(从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁,详细内容不再描述)。

五、lkdlhw_2000个人理解(以下问题都是推测,还没有证实):

隔离级别是由锁来实现的,之所以出现事务的隔离级别相当于数据库开发商根据一般的业务需求实现定义好的一组锁使用的规则,便于我们时候,当我们将事务隔离级别定义到某一级上后如果不能满足需求,我们还可以自行定义sql的锁来覆盖事务隔离级别默认的锁机制?

锁存在两个问题:一个是锁的粒度,一个是锁的时间,锁的时间应该包括两种一种是sql执行完就释放锁,领一中是事务结束后释放锁

六、参考文章

http://www./Channel-4-10-108-0.html
http://tech./art/1105/20050602/261573_1.html
http://www./zhengtengfeng/archive/2007/04/23/113025.html

七、事务隔离级别的例子

1. Read Uncommitted:最低等级的事务隔离,仅仅保证了读取过程中不会读取到非法数据。上诉4种不确定情况均有可能发生。
2. Read Committed
:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了脏读取。该级别适用于大多数系统。
第一个查询事务
SET TRANSACTION ISOLATION LEVEL   Read Committed
begin tran
   update Cate SET Sname=Sname+'b' where ID=1
   SELECT * FROM cate where ID=1
   waitfor delay '00:00:6'  
   rollback tran --
回滚事务
select Getdate()
SELECT * FROM cate where ID=1
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed   --
committed换成Read uncommitted可看到脏读取的示例。
SELECT * FROM cate where ID=1
select Getdate()
可以看到使用 Read Committed 成功的避免了脏读取”.
3. Repeatable Read
:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了脏读取不可重复读取的情况,但是带来了更多的性能损失。
第一个查询事务
SET TRANSACTION ISOLATION LEVEL Repeatable Read --  
Repeatable Read换成Read committed可以看到不可重复读取的示例
begin tran
SELECT * FROM cate where ID=33 --
第一次读取数据
   waitfor delay '00:00:6'  
SELECT * FROM cate where ID=33 --
第二次读取数据,不可重复读取
commit
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed
update cate set Sname=Sname+'JD' where ID=33
SELECT * FROM cate where ID>30
4. Serializable
:最高等级的事务隔离,上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。
在第一个查询窗口执行
SET TRANSACTION ISOLATION LEVEL Serializable --
Serializable换成Repeatable Read 可看到幻像读的示例
begin tran
SELECT * FROM cate where ID>30 --
第一次读取数据,幻像读的示例
   waitfor delay '00:00:6'   --
延迟6秒读取
SELECT * FROM cate where ID>30 --
第一次读取数据
commit
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed
Delete from cate where ID>33
SELECT * FROM cate where ID>30
创建事务

设置事务级别:SET TRANSACTION ISOLATION LEVEL
开始事务:begin tran
提交事务:COMMIT
回滚事务:ROLLBACK
创建事务保存点:SAVE TRANSACTION savepoint_name
回滚到事务点:ROLLBACK TRANSACTION savepoint_name

 


SQL Server的四种隔离级别

2009-08-04 09:32

SQL Server四种隔离级别知识点整理,特别制作了流程图,方便以后查看!

SET TRANSACTION ISOLATION LEVEL
{

READ UNCOMMITTED

| READ COMMITTED

| REPEATABLE READ

| SERIALIZABLE

}

一、未提交读READ UNCOMMITTED(脏读)
意义:包含未提交数据的读。例如,在多用户环境下,用户B更改了某行。用户A在用户B提交更改之前读取已更改的行。如果此时用户B再回滚更改,则用户A便读取了逻辑上从未存在过的行。(如图演示)

 

演示:
1
)用户B
BEGIN TRAN
UPDATE test SET age=25 WHERE name = ‘AA’
2
)用户A
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
(此句不写即默认为READ COMMITTED模式)
SELECT * FROM test
(此时将查到AAage值为25
3
)用户B
ROLLBACK
(此时撤消了步骤1UPDATE操作,则用户A读到的错误数据被称为脏读)

二、提交读(READ COMMITTED
意义:指定在读取数据时控制共享锁以避免脏读。此隔离等级的主要作用是避免脏读。
演示:
1
)用户B
BEGIN TRAN
UPDATE test SET age=25 WHERE name = ‘AA’
2
)用户A
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT * FROM test
(上句设置了提交读模式,则此时将会查不到数据,显示查询等待中,直到用户B进行了ROLLBACK或者COMMIT操作后,此语句才会生效)

三、不一致的分析REPEATABLE READ(重复读)
意义:在多用户环境下,用户A开了一个事务,并且先对test表的某条记录做了查询(select * from test where name = ‘AA’),接着用户Btest表做了更新并提交(update test set age=25 where name=’AA’),这时A再去查test表中的这条记录,第一次读到的age值为12,第二次为25,两次读到的数据不一样,称之为重复读。(如图演示)

解决办法:
在用户A的事务运行之前,先设定SQL的隔离等级为REPEATABLE READ
SQL
语句为SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
这样在上图第一步中,用户A查询完之后,用户B将无法更新用户A所查询到的数据集中的任何数据(但是可以更新、插入和删除用户A查询到的数据集之外的数据),直到用户A事务结束才可以进行更新,这样就有效的防止了用户在同一个事务中读取到不一致的数据。

四、幻象(SERIALIZABLE
意义:在多用户环境下,用户A开启了一个事务,并查询test表中的所有记录,然后用户B在自己的事务中插入(或删除)了test表中的一条记录并提交事务,此时用户A再去执行前面的查询整张表记录的操作,结果会多出(少了)一条记录,此操作称之为幻象。(如图演示)

解决办法:
在用户A的事务运行之前,先设定SQL的隔离等级为SERIALIZABLE
语句为SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
这样在用户A的事务执行过程中,别的用户都将无法对任何数据进行更新、插入和删除的操作,直到用户A的事务回滚或者提交为止。这是四个隔离级别中限制最大的级别。因为并发级别较低,所以应只在必要时才使用该选项

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多