首頁 資料庫 mysql教程 讲解MSSQL数据库中SQL锁机制和事务隔离级别

讲解MSSQL数据库中SQL锁机制和事务隔离级别

Jun 07, 2016 pm 03:48 PM
mssql sql 事務 資料庫 機制 等級 講解 隔離

锁机制 NOLOCK和READPAST的区别。 1. 开启一个事务执行插入数据的操作。 BEGIN TRAN t INSERT INTO Customer SELECT 'a','a' 2. 执行一条查询语句。 SELECT * FROM Customer WITH (NOLOCK) 结果中显示"a"和"a"。当1中事务回滚后,那么a将成为脏数据。(注:1中

锁机制

NOLOCK和READPAST的区别。

1. 开启一个事务执行插入数据的操作。

BEGIN TRAN t

INSERT INTO Customer

SELECT 'a','a'

2. 执行一条查询语句。

SELECT * FROM Customer WITH (NOLOCK)

结果中显示"a"和"a"。当1中事务回滚后,那么a将成为脏数据。(注:1中的事务未提交) 。NOLOCK表明没有对数据表添加共享锁以阻止其它事务对数据表数据的修改。

SELECT * FROM Customer

这条语句将一直死锁,直到排他锁解除或者锁超时为止。(注:设置锁超时SET LOCK_TIMEOUT 1800)

SELECT * FROM Customer WITH (READPAST)

这条语句将显示a未提交前的状态,但不锁定整个表。这个提示指明数据库引擎返回结果时忽略加锁的行或数据页。

3. 执行一条插入语句。

BEGIN TRAN t

INSERT INTO Customer

SELECT 'b','b'

COMMIT TRAN t

这个时候,即使步骤1的事务回滚,那么a这条数据将丢失,而b继续插入数据库中。

 

NOLOCK

1. 执行如下语句。

BEGIN TRAN ttt

SELECT * FROM Customer WITH (NOLOCK)

WAITFOR delay '00:00:20'

COMMIT TRAN ttt

注:NOLOCK不加任何锁,可以增删查改而不锁定。

INSERT INTO Customer SELECT 'a','b' –不锁定

DELETE Customer where ID=1 –不锁定

SELECT * FROM Customer –不锁定

UPDATE Customer SET Title='aa' WHERE ID=1 –不锁定

 

ROWLOCK

1. 执行一条带行锁的查询语句。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ -- (必须)

BEGIN TRAN ttt

SELECT * FROM Customer WITH (ROWLOCK) WHERE ID=17

WAITFOR delay '00:00:20'

COMMIT TRAN ttt

注:在删除和更新正在查询的数据时,会锁定数据。对其他未查询的行和增加,查询数据无影响。

INSERT INTO Customer SELECT 'a','b' –不等待

 

DELETE Customer where ID=17 –等待

DELETE Customer where ID17 –不等待

 

SELECT * FROM Customer –不等待

 

UPDATE Customer SET Title='aa' WHERE ID=17–等待

UPDATE Customer SET Title='aa' WHERE ID17–不等待

HOLDLOCK,TABLOCK和TABLOCKX

1. 执行HOLDLOCK

BEGIN TRAN ttt

SELECT * FROM Customer WITH (HOLDLOCK)

WAITFOR delay '00:00:10'

COMMIT TRAN ttt

注:其他事务可以读取表,但不能更新删除

update Customer set Title='aa' —要等待10秒中。

SELECT * FROM Customer —不需要等待

2. 执行TABLOCKX

BEGIN TRAN ttt

SELECT * FROM Customer WITH (TABLOCKX)

WAITFOR delay '00:00:10'

COMMIT TRAN ttt

注:其他事务不能读取表,更新和删除

update Customer set Title='aa' —要等待10秒中。

SELECT * FROM Customer —要等待10秒中。

3. 执行TABLOCK

BEGIN TRAN ttt

SELECT * FROM Customer WITH (TABLOCK)

WAITFOR delay '00:00:10'

COMMIT TRAN ttt

注:其他事务可以读取表,但不能更新删除

update Customer set Title='aa' —要等待10秒中。

SELECT * FROM Customer —不需要等待

UDPLOCK

1. 在A连接中执行。

BEGIN TRAN ttt

SELECT * FROM Customer WITH (UPDLOCK)

WAITFOR delay '00:00:10'

COMMIT TRAN ttt

2. 在其他连接中执行。

update Customer set Title='aa' where ID=1—要等10秒

SELECT * FROM Customer –不用等

insert into Customer select 'a','b'–不用等

注:对于UDPLOCK锁,只对更新数据锁定。

 

注:使用这些选项将使系统忽略原先在SET语句设定的事务隔离级别(SET Transaction Isolation Level)。

 

事务隔离级别

脏读:READ UNCOMMITTED

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。

1. 在A连接中执行。

BEGIN TRAN t

INSERT INTO Customer

SELECT '123','123'

WAITFOR delay '00:00:20'

COMMIT TRAN t

2. 在B连接中执行。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

SELECT * FROM Customer

这个时候,未提交的数据会'123'会显示出来,当A事务回滚时就导致了脏数据。相当于(NOLOCK)

提交读:READ COMMITTED

1. 在A连接中执行。

BEGIN TRAN t

INSERT INTO Customer

SELECT '123','123'

WAITFOR delay '00:00:20'

COMMIT TRAN t

2. 在B连接中执行。

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SELECT * FROM Customer

这个时候,未提交的数据会'123'不会显示出来,当A事务提交以后B中才能读取到数据。避免了脏读。

不可重复读:REPEATABLE READ

不可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

例如:

1. 在A连接中执行如下语句。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

BEGIN TRAN ttt

SELECT * FROM Customer WHERE ID=17

WAITFOR delay '00:00:30'

SELECT * FROM Customer WHERE ID=17

COMMIT TRAN ttt

2. 在B连接中执行如下语句,而且要在第一个事物的三十秒等待内。

UPDATE Customer SET Title='d' WHERE ID=17

这个时候,此连接将锁住不能执行,一直等到A连接结束为止。而且A连接中两次读取到的数据相同,不受B连接干扰。

注,对于Read Committed和Read UnCommitted情况下,B连接不会锁住,等到A连接执行完以后,两条查询语句结果不同,即第二条查询的Title变成了d。

序列化读:SERIALIZABLE

 

 

1. 在A连接中执行。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN t

UPDATE Customer SET Title='111'

WAITFOR delay '00:00:20'

COMMIT TRAN t

2. 在B连接中执行,并且要在A执行后的20秒内。

BEGIN TRAN tt

INSERT INTO Customer

SELECT '2','2'

COMMIT TRAN tt

在A连接的事务提交之前,B连接无法插入数据到表中,这就避免了幻觉读。

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

共享锁

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

更新锁

更新锁(U 锁)可以防止常见的死锁。在可重复读或可序列化事务中,此事务读取数据 [获取资源(页或行)的共享锁(S 锁)],然后修改数据 [此操作要求锁转换为排他锁(X 锁)]。如果两个事务获得了资源上的共享模式锁,然后试图同时更新数据,则一个事务尝试将锁转换为排他锁(X 锁)。共享模式到排他锁的转换必须等待一段时间,因为一个事务的排他锁与其他事务的共享模式锁不兼容;发生锁等待。第二个事务试图获取排他锁(X 锁)以进行更新。由于两个事务都要转换为排他锁(X 锁),并且每个事务都等待另一个事务释放共享模式锁,因此发生死锁。

若要避免这种潜在的死锁问题,请使用更新锁(U 锁)。一次只有一个事务可以获得资源的更新锁(U 锁)。如果事务修改资源,则更新锁(U 锁)转换为排他锁(X 锁)。

排他锁

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

数据修改语句(如 INSERT、UPDATE 和 DELETE)合并了修改和读取操作。语句在执行所需的修改操作之前首先执行读取操作以获取数据。因此,数据修改语句通常请求共享锁和排他锁。例如,UPDATE 语句可能根据与一个表的联接修改另一个表中的行。在此情况下,除了请求更新行上的排他锁之外,UPDATE 语句还将请求在联接表中读取的行上的共享锁。

 

 

 

下面的示例显示   SQL   Server   中当前持有的所有锁的信息。  
    
  USE   master  
  EXEC   sp_lock  
    
  其中"类型"列显示当前锁定的资源类型。  
    
  资源类型   描述    
  RID   用于锁定表中的一行的行标识符。    
  KEY   索引中的行锁。用于保护可串行事务中的键范围。    
  PAG   数据或索引页。    
  EXT   相邻的八个数据页或索引页构成的一组。    
  TAB   包括所有数据和索引在内的整个表。    
  DB   数据库。    
    
    
  如何查看当前锁(企业管理器)  
    
  展开服务器组,然后展开服务器。  
    
    
  展开"管理",然后展开"当前活动"。  
    
    
  执行下列操作中的一种:    
  展开"锁/进程   ID"以查看每个连接的当前锁。  
    
    
  展开"锁/对象"以查看每个对象的当前锁。    
  在控制台树中单击要查看的连接   (SPID)   或对象。    
  该连接或对象的当前锁显示在详细信息窗格中。  
    
  SQL   Server   使用以下资源锁模式。  
    
  锁模式   描述    
  共享   (S)   用于不更改或不更新数据的操作(只读操作),如   SELECT   语句。    
  更新   (U)   用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。    
  排它   (X)   用于数据修改操作,例如   INSERT、UPDATE   或   DELETE。确保不会同时对同一资源进行多重更新。    
  意向   用于建立锁的层次结构。意向锁的类型为:意向共享   (IS)、意向排它   (IX)   以及与意向排它共享   (SIX)。    
  架构   在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改   (Sch-M)   和架构稳定性   (Sch-S)。      
  大容量更新   (BU)   向表中大容量复制数据并指定了   TABLOCK   提示时使用。    
    
  虽然   Microsoft®   SQL   Server™   2000   自动执行锁定,但它仍可以通过以下方法自定义应用程序中的锁定:    
    
  处理死锁和设置死锁优先级。  
    
  处理超时和设置锁超时持续时间。  
    
  设置事务隔离级别。  
    
  对   SELECT、INSERT、UPDATE   和   DELETE   语句使用表级锁定提示。  
    
  配置索引的锁定粒度。    
    
    
  可以使用   SELECT、INSERT、UPDATE   和   DELETE   语句指定表级锁定提示的范围,以引导   Microsoft®   SQL   Server™   2000   使用所需的锁类型。当需  
    
  要对对象所获得锁类型进行更精细控制时,可以使用表级锁定提示。这些锁定提示取代了会话的当前事务隔离级别。  
    
  说明     SQL   Server   查询优化器自动作出正确的决定。建议仅在必要时才使用表级锁定提示更改默认的锁定行为。禁止锁定级别反过来会影响并发  
    
  。  
    
  锁定提示   描述    
  HOLDLOCK   将共享锁保留到事务完成,而不是在相应的表、行或数据页不再需要时就立即释放锁。HOLDLOCK   等同于   SERIALIZABLE。    
  NOLOCK   不要发出共享锁,并且不要提供排它锁。当此选项生效时,可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅  
    
  应用于   SELECT   语句。    
  PAGLOCK   在通常使用单个表锁的地方采用页锁。    
  READCOMMITTED   用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL   Server   2000   在此隔离级别上操作。    
  READPAST   跳过锁定行。此选项导致事务跳过由其它事务锁定的行(这些行平常会显示在结果集内),而不是阻塞该事务,使其等待其它事务释放  
    
  在这些行上的锁。READPAST   锁提示仅适用于运行在提交读隔离级别的事务,并且只在行级锁之后读取。仅适用于   SELECT   语句。    
  READUNCOMMITTED   等同于   NOLOCK。    
  REPEATABLEREAD   用与运行在可重复读隔离级别的事务相同的锁语义执行扫描。      
  ROWLOCK   使用行级锁,而不使用粒度更粗的页级锁和表级锁。    
  SERIALIZABLE   用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于   HOLDLOCK。    
  TABLOCK   使用表锁代替粒度更细的行级锁或页级锁。在语句结束前,SQL   Server   一直持有该锁。但是,如果同时指定   HOLDLOCK,那么在事务结束  
    
  之前,锁将被一直持有。    
  TABLOCKX   使用表的排它锁。该锁可以防止其它事务读取或更新表,并在语句或事务结束前一直持有。    
  UPDLOCK   读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK   的优点是允许您读取数据(不阻塞其它事务)并  
    
  在以后更新数据,同时确保自从上次读取数据后数据没有被更改。    
  XLOCK   使用排它锁并一直保持到由语句处理的所有数据上的事务结束时。可以使用   PAGLOCK   或   TABLOCK   指定该锁,这种情况下排它锁适用于适当  
    
  级别的粒度。    
    
    
  例如,如果将事务隔离级别设置为   SERIALIZABLE,并且在   SELECT   语句中使用表级锁定提示   NOLOCK,则键范围锁通常用于维护不采用可串行事务  
    
  。  
  USE   pubs  
  GO  
  SET   TRANSACTION   ISOLATION   LEVEL   SERIALIZABLE  
  GO  
  BEGIN   TRANSACTION  
  SELECT   au_lname   FROM   authors   WITH   (NOLOCK)  
  GO  

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1320
25
PHP教程
1269
29
C# 教程
1249
24
iOS 18 新增「已復原」相簿功能 可找回遺失或損壞的照片 iOS 18 新增「已復原」相簿功能 可找回遺失或損壞的照片 Jul 18, 2024 am 05:48 AM

蘋果公司最新發布的iOS18、iPadOS18以及macOSSequoia系統為Photos應用程式增添了一項重要功能,旨在幫助用戶輕鬆恢復因各種原因遺失或損壞的照片和影片。這項新功能在Photos應用的"工具"部分引入了一個名為"已恢復"的相冊,當用戶設備中存在未納入其照片庫的圖片或影片時,該相冊將自動顯示。 "已恢復"相簿的出現為因資料庫損壞、相機應用未正確保存至照片庫或第三方應用管理照片庫時照片和視頻丟失提供了解決方案。使用者只需簡單幾步

如何在PHP中處理資料庫連線錯誤 如何在PHP中處理資料庫連線錯誤 Jun 05, 2024 pm 02:16 PM

PHP處理資料庫連線報錯,可以使用下列步驟:使用mysqli_connect_errno()取得錯誤代碼。使用mysqli_connect_error()取得錯誤訊息。透過擷取並記錄這些錯誤訊息,可以輕鬆識別並解決資料庫連接問題,確保應用程式的順暢運作。

在PHP中使用MySQLi建立資料庫連線的詳盡教學 在PHP中使用MySQLi建立資料庫連線的詳盡教學 Jun 04, 2024 pm 01:42 PM

如何在PHP中使用MySQLi建立資料庫連線:包含MySQLi擴充(require_once)建立連線函數(functionconnect_to_db)呼叫連線函數($conn=connect_to_db())執行查詢($result=$conn->query())關閉連線( $conn->close())

如何在 Golang 中使用資料庫回呼函數? 如何在 Golang 中使用資料庫回呼函數? Jun 03, 2024 pm 02:20 PM

在Golang中使用資料庫回呼函數可以實現:在指定資料庫操作完成後執行自訂程式碼。透過單獨的函數新增自訂行為,無需編寫額外程式碼。回調函數可用於插入、更新、刪除和查詢操作。必須使用sql.Exec、sql.QueryRow或sql.Query函數才能使用回呼函數。

如何在 Golang 中將 JSON 資料保存到資料庫中? 如何在 Golang 中將 JSON 資料保存到資料庫中? Jun 06, 2024 am 11:24 AM

可以透過使用gjson函式庫或json.Unmarshal函數將JSON資料儲存到MySQL資料庫中。 gjson函式庫提供了方便的方法來解析JSON字段,而json.Unmarshal函數需要一個目標類型指標來解組JSON資料。這兩種方法都需要準備SQL語句和執行插入操作來將資料持久化到資料庫中。

mysql:簡單的概念,用於輕鬆學習 mysql:簡單的概念,用於輕鬆學習 Apr 10, 2025 am 09:29 AM

MySQL是一個開源的關係型數據庫管理系統。 1)創建數據庫和表:使用CREATEDATABASE和CREATETABLE命令。 2)基本操作:INSERT、UPDATE、DELETE和SELECT。 3)高級操作:JOIN、子查詢和事務處理。 4)調試技巧:檢查語法、數據類型和權限。 5)優化建議:使用索引、避免SELECT*和使用事務。

PHP 資料庫連線陷阱:避免常見的錯誤和誤區 PHP 資料庫連線陷阱:避免常見的錯誤和誤區 Jun 05, 2024 pm 10:21 PM

若要避免PHP資料庫連線錯誤,請遵循最佳實務:檢查連線錯誤,變數名稱與憑證相符。使用安全儲存或環境變量,避免硬編碼憑證。使用完後關閉連接,防止SQL注入,使用準備好的語句或綁定參數。

MySQL:世界上最受歡迎的數據庫的簡介 MySQL:世界上最受歡迎的數據庫的簡介 Apr 12, 2025 am 12:18 AM

MySQL是一種開源的關係型數據庫管理系統,主要用於快速、可靠地存儲和檢索數據。其工作原理包括客戶端請求、查詢解析、執行查詢和返回結果。使用示例包括創建表、插入和查詢數據,以及高級功能如JOIN操作。常見錯誤涉及SQL語法、數據類型和權限問題,優化建議包括使用索引、優化查詢和分錶分區。

See all articles