`

数据库中的事务和锁

阅读更多

数据库中的事务和锁

一、事务的ACID特性

1A (Atomicity)  原子性

事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

2C (Consistency)一致性

事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B树索引或双向链表)都必须是正确的。

3I (Isolation)   隔离性 

并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务识别数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是第二个事务修改它之后的状态,事务不会识别中间状态的数据。

4D (Durability)  持久性

事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。

 

二、完整的事务

BEGIN a transaction: 设置事务的起始点

COMMIT a transaction: 提交事务,使事务提交的数据成为持久,不可更改的部分.

ROLLBACK a transaction:撤消一个事务,使之成为事务开始前的状态.

SAVE a transaction:建立一个标签,做为部分回滚时使用,使之恢复到标签初的状态.

 

事务的语法:

BEGIN TRAN[SACTION] [<transaction name>|<@transaction variable>][WITH MARK [’<description>’]][;] 

COMMIT [TRAN[SACTION] [<transaction name>|<@transaction variable>]][;]

ROLLBACK TRAN[SACTION] [<transaction name>|<save point name>|<@transaction variable>|<@savepoint variable>][;]

SAVE TRAN[SACTION] [<save point name>| <@savepoint variable>][;]

 

事务完整的例子:

USE AdventureWorks2008; -- We’re making our own table - what DB doesn’t matter
-- Create table to work with
CREATE TABLE MyTranTest
(
OrderID INT PRIMARY KEY IDENTITY
);
-- Start the transaction
BEGIN TRAN TranStart;
-- Insert our first piece of data using default values.
-- Consider this record No1. It is also the 1st record that stays
-- after all the rollbacks are done.
INSERT INTO MyTranTest
DEFAULT VALUES;
-- Create a "Bookmark" to come back to later if need be
SAVE TRAN FirstPoint;
-- Insert some more default data (this one will disappear
-- after the rollback).
-- Consider this record No2.
INSERT INTO MyTranTest
DEFAULT VALUES;
-- Roll back to the first savepoint. Anything up to that
-- point will still be part of the transaction. Anything
-- beyond is now toast.
ROLLBACK TRAN FirstPoint;
INSERT INTO MyTranTest
DEFAULT VALUES;
-- Commit the transaction
COMMIT TRAN TranStart;
-- See what records were finally committed.
SELECT TOP 2 OrderID
FROM MyTranTest
ORDER BY OrderID DESC;
-- Clean up after ourselves
DROP TABLE MyTranTest;


 

 

三、锁

锁定是 Microsoft SQL Server数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制。

在事务获取数据块当前状态的依赖关系(比如通过读取或修改数据)之前,它必须保护自己不受其他事务对同一数据进行修改的影响。事务通过请求锁定数据块来达到此目的。锁有多种模式,如共享或独占。锁模式定义了事务对数据所拥有的依赖关系级别。如果某个事务已获得特定数据的锁,则其他事务不能获得会与该锁模式发生冲突的锁。如果事务请求的锁模式与已授予同一数据的锁发生冲突,则数据库引擎实例将暂停事务请求直到第一个锁释放。

 

四大冲突问题

1、脏读

某个事务读取的数据是另一个事务正在处理的数据。而另一个事务可能会回滚,造成第一个事务读取的数据是错误的。

 

2、不可重复读

在一个事务里两次读入数据,但另一个事务已经更改了第一个事务涉及到的数据,造成第一个事务读入旧数据。

 

3、幻读

幻读是指当事务不是独立执行时发生的一种现象。例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

 

4、更新丢失

多个事务同时读取某一数据,一个事务成功处理好了数据,被另一个事务写回原值,造成第一个事务更新丢失。

 

锁模式:

1、共享锁

共享锁(S 锁)允许并发事务在封闭式并发控制下读取 (SELECT)资源。有关详细信息,请参阅并发控制的类型资源上存在共享锁(S锁)时,任何其他事务都不能修改数据。读取操作一完成,就立即释放资源上的共享锁(S锁),除非将事务隔离级别设置为可重复读或更高级别,或者在事务持续时间内用锁定提示保留共享锁(S锁)。

2、更新锁(U锁)

更新锁在共享锁和排他锁的杂交。更新锁意味着在做一个更新时,一个共享锁在扫描完成符合条件的数据后可能会转化成排他锁。

 

这里面有两个步骤:

1) 扫描获取Where条件时。这部分是一个更新查询,此时是一个更新锁。

2) 如果将执行写入更新。此时该锁升级到排他锁。否则,该锁转变成共享锁。

 

更新锁可以防止常见的死锁。

 

3、排他锁

排他锁(X 锁)可以防止并发事务对资源进行访问。排他锁不与其他任何锁兼容。使用排他锁(X锁)时,任何其他事务都无法修改数据;仅在使用 NOLOCK提示或未提交读隔离级别时才会进行读取操作。

 

事务隔离级别 

SQL Server通过SET TRANSACTION ISOLATION LEVEL语句设置事务隔离级别: 

SET TRANSACTION ISOLATION LEVEL

    { READ UNCOMMITTED

    | READ COMMITTED

    | REPEATABLE READ

    | SNAPSHOT

    | SERIALIZABLE

    }

[ ; ]

 

Read CommittedSQL Server和Oracle的预设隔离等级。

 

 

1READ UNCOMMITTED

Read UnCommitted事务可以读取事务已修改,但未提交的的记录。

Read UnCommitted事务会产生脏读(Dirty Read)。

Read UnCommitted事务与select语句加nolock的效果一样,它是所有隔离级别中限制最少的。

 

2READ COMMITTED

一旦创建共享锁的语句执行完成,该锁顶便释放。

Read CommittedSQL Server的预设隔离等级。

Read Committed只可以防止脏读。

--先创建表: 
CREATE TABLE tb(id int,val int) 
INSERT tb VALUES(1,10) 
INSERT tb VALUES(2,20) 
  
然后在连接1中,执行: 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
BEGIN TRANSACTION
    SELECT * FROM tb;  --这个SELECT结束后,就会释放掉共享锁 
      
    WAITFOR DELAY '00:00:05'  --模拟事务处理,等待5秒 
      
    SELECT * FROM tb;   --再次SELECT tb表 
ROLLBACK  --回滚事务 
  
在连接2中,执行 
UPDATE tb SET
    val = val + 10 
WHERE id = 2; 
  
-------- 
回到连接1中.可以看到.两次SELECT的结果是不同的. 
因为在默认的READ COMMITTED隔离级别下,SELECT完了.就会马上释放掉共享锁. 


 

 

3REPEATABLE READ

REPEATABLE READ事务不会产生脏读,并且在事务完成之前,任何其它事务都不能修改目前事务已读取的记录。

其它事务仍可以插入新记录,但必须符合当前事务的搜索条件——这意味着当前事务重新查询记录时,会产生幻读(Phantom Read)。

 

4SERIALIZABLE

SERIALIZABLE可以防止除更新丢失外所有的一致性问题,:

 

1.语句无法读取其它事务已修改但未提交的记录。

2.在当前事务完成之前,其它事务不能修改目前事务已读取的记录。

3.在当前事务完成之前,其它事务所插入的新记录,其索引键值不能在当前事务的任何语句所读取的索引键范围中。

 

5SNAPSHOT

Snapshot事务中任何语句所读取的记录,都是事务启动时的数据。

这相当于事务启动时,数据库为事务生成了一份专用快照。在当前事务中看到不其它事务在当前事务启动之后所进行的数据修改。

Snapshot事务不会读取记录时要求锁定,读取记录的Snapshot事务不会锁住其它事务写入记录,写入记录的事务也不会锁住Snapshot事务读取数据。

 

四、悲观锁和乐观锁

1、悲观锁

悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。
悲观锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直阻塞,直到这个事务结束.
悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的资源,以此保证读取数据一致性,避免修改丢失。

悲观锁可以使用Repeatable Read事务,它完全满足悲观锁的要求。


2、乐观锁

乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。

如果使用乐观锁,那么数据库就必须加版本字段,否则就只能比较所有字段,但因为浮点类型不能比较,所以实际上没有版本字段是不可行的。

 

3、死锁

当二或多个工作各自具有某个资源的锁定,但其它工作尝试要锁定此资源,而造成工作永久封锁彼此时,会发生死锁。例如:
1.          
事务 A取得数据列 1 的共享锁定。
2.          
事务B取得数据列 2 的共享锁定。
3.          
事务A现在要求数据列 2 的独占锁定,但会被封锁直到事务B 完成并释出对数据列 2 的共享锁定为止。
4.          
事务B现在要求数据列 1 的独占锁定,但会被封锁直到事务A 完成并释出对数据列 1 的共享锁定为止。
等到事务B 完成后,事务A 才能完成,但事务B被事务A 封锁了。这个状况也称为「循环相依性」(Cyclic Dependency)。事务A相依于事务B,并且事务B也因为相依于事务A 而封闭了这个循环。

 

SQL Server遇到死锁时会自动杀死其中一个事务,而另一个事务会正常结束(提交或回滚)。

SQL Server对杀死的连接返回错误代码是1205,异常提示是:

Your transaction (process ID #52) was deadlocked on {lock | communication buffer | thRead} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.

 

例如以下操作就会产生死锁,两个连接互相阻塞对方的update

连接1: 
begin tran 
  
select * from customers  
  
update customers set CompanyName = CompanyName 
  
   
waitfor delay '00:00:05'
  
   
select * from Employees 
–因为Employees被连接2锁住了,所以这里会阻塞。 
update Employees set LastName = LastName  
commit tran 
   
连接2: 
begin tran 
  
select * from Employees 
  
update Employees set LastName = LastName 
  
   
waitfor delay '00:00:05'
  
   
select * from customers  
--因为customers被连接1锁住了,所以这里会阻塞。 
update customers set CompanyName = CompanyName 
commit tran


 

 

4、如何避免死锁

(1).按同一顺序访问对象。(注:避免出现循环)
(2).
避免事务中的用户交互。(注:减少持有资源的时间,较少锁竞争)
(3).
保持事务简短并处于一个批处理中。(注:同(2),减少持有资源的时间)
(4).
使用较低的隔离级别。(注:使用较低的隔离级别(例如已提交读)比使用较高的隔离级别(例如可序列化)持有共享锁的时间更短,减少锁竞争)
(5).
使用基于行版本控制的隔离级别:2005中支持快照事务隔离和指定READ_COMMITTED隔离级别的事务使用行版本控制,可以将读与写操作之间发生的死锁几率降至最低:
SET ALLOW_SNAPSHOT_ISOLATION ON --
事务可以指定 SNAPSHOT事务隔离级别;
SET READ_COMMITTED_SNAPSHOT ON  --
指定 READ_COMMITTED隔离级别的事务将使用行版本控制而不是锁定。默认情况下(没有开启此选项,没有加with nolock提示)SELECT语句会对请求的资源加S(共享锁);而开启了此选项后,SELECT不会对请求的资源加S锁。
注意:设置 READ_COMMITTED_SNAPSHOT选项时,数据库中只允许存在执行 ALTER DATABASE命令的连接。在 ALTER DATABASE完成之前,数据库中决不能有其他打开的连接。数据库不必一定要处于单用户模式中。
(6).
使用绑定连接。(注:绑定会话有利于在同一台服务器上的多个会话之间协调操作。绑定会话允许一个或多个会话共享相同的事务和锁(但每个回话保留其自己的事务隔离级别),并可以使用同一数据,而不会有锁冲突。可以从同一个应用程序内的多个会话中创建绑定会话,也可以从包含不同会话的多个应用程序中创建绑定会话。在一个会话中开启事务(begin tran)后,调用exec sp_getbindtoken @Token out;来取得Token,然后传入另一个会话并执行EXEC sp_bindsession @Token来进行绑定(最后的示例中演示了绑定连接)

 

五、.NET中使用指定的隔离级别开始一个事务

BeginTransaction函数有多个重载,其中一个可以指定事务的隔离级别

BeginTransaction(IsolationLevel):以指定的隔离级别启动数据库事务。

 

注意:在事务提交或回滚后,该事务的隔离级别为自动提交模式的所有后续命令保存 ( SQL Server默认设置) 中。这样将产生意外结果,例如 REPEATABLE READ隔离级别持续并阻止其他用户使用某一行。若要重置隔离级别为默认值 (读取操作),执行 Transact-SQL 设置事务隔离级别读作的语句或调用SqlConnection.BeginTransaction 后面紧跟SqlTransaction.Commit

 

更多详细信息请查看java教程网 http://www.itchm.com/forum-59-1.html
分享到:
评论

相关推荐

    数据库中事务和锁.ppt

    在数据库管理系统中,事务和锁是两个至关重要的概念,它们主要用于保证数据的一致性和完整性,以及在多用户环境下的并发访问控制。 事务是数据库操作的基本单位,它封装了一组数据库操作,这些操作要么全部执行,...

    数据库安全事务与锁数据库安全事务与锁

    数据库安全事务与锁是数据库管理系统中的关键概念,它们确保了多用户环境下数据的一致性和完整性。在SQL Server 2000中,事务和锁机制对于保证数据库系统的并发操作和数据安全性至关重要。 1. **事务**: 事务是...

    数据库事务、hibernate悲观锁和乐观锁

    数据库事务是数据库操作的核心组成部分,它确保了数据的一致性和完整性。事务是由一系列数据库操作组成的逻辑单元,这些操作要么全部成功执行,要么全部不执行,遵循ACID(原子性、一致性、隔离性和持久性)原则。 ...

    一次长事务导致数据库锁等待超时问题跟踪

    一次长事务可能会占用大量资源,导致其他并发事务出现锁等待,甚至超时,严重影响数据库的性能和正常服务。本篇文章将深入探讨这个问题,从原因、表现、诊断到解决策略进行详细分析。 一、长事务的定义与特征 长...

    数据库的事务与锁

    ### 数据库的事务与锁 #### 一、事务的ACID特性 事务处理是数据库管理系统(DBMS)的核心功能之一,确保了数据的一致性和可靠性。事务处理中的ACID特性是评估事务处理性能的重要标准。 ##### A(Atomicity)原子性 -...

    数据库事务管理及锁.xmind

    数据库事务管理及锁机制原理剖析:包括事务特性 ACID、数据隔离级别、事务实现的原理、锁机制,及过程中可能遇到的查询效率及死锁问题等

    数据库之事务调优

    数据库之事务调优是数据库管理中的一个重要环节,它关乎到系统的性能、稳定性和并发处理能力。事务是数据库操作的基本单位,确保数据的一致性、...通过这些方法,我们可以构建出一个高效、稳定的数据库事务处理系统。

    数据库事务及锁机制面试题

    ### 数据库事务及锁机制详解 #### 一、事务的概念与特性 事务是数据库系统中一组操作的集合,用于确保数据的一致性和完整性。在事务处理中,事务被视为一个不可分割的工作单元,其中包含的操作要么全部成功,要么...

    数据库中事物与锁的课件

    总结来说,事务和锁在数据库管理系统中起着至关重要的作用,它们保证了数据的一致性和可靠性,尤其是在多用户并发访问的环境中。事务控制语句提供了对事务生命周期的精细管理,而锁则用来解决并发问题,避免数据竞争...

    sybase数据库查被锁的表.doc

    Sybase 数据库锁机制和锁表查询 Sybase 数据库锁机制是指...Sybase 数据库锁机制和锁表查询是数据库管理系统中非常重要的组件,可以帮助数据库管理员了解和优化数据库中的锁情况,从而提高数据库的性能和可靠性。

    数据库事务总结 数据库事务总结

    ### 数据库事务总结 #### 一、事务的基本概念与特性 **事务**是数据库系统中的一个逻辑工作单元,它由一系列的操作组成,这些操作要么都完成,要么都不完成,以此来保证数据的一致性和完整性。 #### 二、事务的...

    数据库中锁机制的学习

    数据库中的锁机制是确保数据一致性、并发控制和事务隔离的重要机制。在多用户环境中,当多个用户同时访问和操作同一份数据时,可能会引发数据冲突和不一致。为了解决这些问题,数据库系统引入了锁来协调并发操作。...

    MySQL数据库-事务、锁及SQL优化

    MySQL数据库的事务、锁以及SQL优化是数据库管理中至关重要的概念,它们对于数据一致性、并发控制和系统性能有着直接影响。 1. **事务**:事务是数据库操作的基本单元,确保一系列数据库操作要么全部成功,要么全部...

    浅谈数据库中事务处理和并发控制技术

    数据库事务处理和并发控制是数据库管理系统(DBMS)中的核心技术, Guarantees 数据库的可靠性和一致性。本文将详细介绍数据库事务处理和并发控制技术的概念、特性和实现机制。 一、事务处理概念 事务处理是数据库...

    MS SQL Server数据库事务锁机制分析

    MS SQL Server 数据库的事务锁机制是确保数据库完整性和一致性的关键组成部分,它涉及到多用户环境下的并发控制和数据安全。锁是一种软件机制,用于防止多个用户在同一时间对同一资源进行冲突操作,确保数据的一致性...

    浅析SQL Server数据库事务锁机制.pdf

    在介绍SQL Server数据库事务锁机制之前,首先需要了解锁的概念。锁是网络数据库中的一个非常重要的概念,主要用于在多...随着信息技术的不断发展,对于数据库事务锁的理解和应用也需要不断更新,以适应新的挑战和要求。

    事务和锁(数据库开发必备)

    在数据库开发中,事务和锁是两个至关重要的概念,它们对于数据一致性、并发控制和多用户环境下的数据安全起着核心作用。理解并熟练运用事务和锁,是每个数据库开发者必须掌握的基础知识。 首先,我们来详细探讨事务...

    数据库系统工程师-06事务和锁.doc

    在数据库系统中,事务和锁是核心概念,它们对于确保数据的完整性和一致性至关重要。事务是一系列数据库操作的逻辑单元,它具有四个关键特性,通常被称为ACID特性。 1. **原子性(Atomicity)**:事务中的所有操作被视...

    数据库锁和事务的详细讲解

    详细描述数据库锁和事务的内容,其中包括各种类型的锁的讲述,事务的控制

Global site tag (gtag.js) - Google Analytics