db事务级别及锁

相关sql

事务A

BEGIN TRANSACTION

    --执行修改 获取排他锁
    UPDATE Product
    SET Price = 10
    WHERE Id = 1

    --阶段2
    UPDATE Product
    SET Price = Price + 1
    WHERE Id = 1 

    SELECT * FROM Product
    WHERE Id = 1 

    --阶段3
    UPDATE Product
    SET Price = Price + 5
    WHERE Id = 1 

    SELECT * FROM Product
    WHERE Id = 1 

--阶段4
COMMIT TRANSACTION

事务B

--2.隔离级别的分类
--(1)未提交读 (READ UNCOMMITTED)

--(2)已提交读(READ COMMITTED)(默认值)

--(3)可重复读(REPEATABLE READ)

--(4)可序列化(SERIALIZABLE)

--(5)快照(SNAPSHOT)

--(6)已经提交读快照(READ_COMMITTED_SNAPSHOT)

--BEGIN TRANSACTION

--  --未提交读
--  SET TRAN ISOLATION LEVEL READ UNCOMMITTED

--  SELECT * FROM Product--与事务A各阶段显示相同
--  WHERE Id = 1 

--(1)读操作可以读取未提交的修改(也称为脏读)。

--(2)读操作不会妨碍写操作请求排他锁,其他事务正在进行读操作时,写操作可以同时对这些数据进行修改。

--(3)事务A进行了多次修改,事务B在不同阶段进行查询时可能会有不同的结果。
--COMMIT TRANSACTION



--BEGIN TRANSACTION

--  --已提交读【默认级别】
--  SET TRAN ISOLATION LEVEL READ COMMITTED

--  --读取获取共享锁  
--  --当查询信息具有排他锁 需等待至排他锁结束
--  SELECT * FROM Product--与事务A各阶段显示相同
--  WHERE Id = 1 

----(1)必须获得共享锁才能进行读操作,其他事务如果对该资源持有排他锁,则共享锁必须等待排他锁释放。

----(2)读操作不能读取未提交的修改,读操作读取到的数据是提交过的修改。

----(3)读操作不会在事务持续期间内保留共享锁,其他事务可以在两个读操作之间更改数据资源,读操作因而可能每次得到不同的取值。这种现象称为“不可重复读”
    
--COMMIT TRANSACTION

--★ 3.可重复读(REPEATABLE READ)
--BEGIN TRANSACTION

--  SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
--  SELECT * FROM Product WHERE Id = 1

--(1)必须获得共享锁才能进行读操作,获得的共享锁将一直保持直到事务完成之止。

--(2)在获得共享锁的事务完成之前,没有其他事务能够获得排他锁修改这一数据资源,这样可以保证实现可重复的读取。

--(3)两个事务在第一次读操作之后都将保留它们获得的共享锁,所以任何一个事务都不能获得为了更新数据而需要的排他锁,这种情况将会导致死锁(deadlock),不过却避免了更新冲突。

--COMMIT TRANSACTION

--★ 4.可序列化(SERIALIZABLE)
BEGIN TRANSACTION

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    SELECT * FROM Product WHERE Id = 1

--“可序列化(SERIALIZABLE)”隔离级别的含义:

--(1)必须获得共享锁才能进行读操作,获得的共享锁将一直保持直到事务完成之止。

--(2)在获得共享锁的事务完成之前,没有其他事务能够获得排他锁修改这一数据资源,且当其他事务增加能够满足当前事务的读操作的查询搜索条件的新行时,其他事务将会被阻塞,直到当前事务完成然后释放共享锁,其他事务才能获得排他锁进行插入操作。

--(3)事务中的读操作在任何情况下读取到的数据是一致的,不会出现幻影行(幻读)。

--(4)范围锁:读操作锁定满足查询搜索条件范围的锁

COMMIT TRANSACTION

相关信息

--2.隔离级别的分类
--(1)未提交读 (READ UNCOMMITTED)

--(2)已提交读(READ COMMITTED)(默认值)

--(3)可重复读(REPEATABLE READ)

--(4)可序列化(SERIALIZABLE)

--(5)快照(SNAPSHOT)

--(6)已经提交读快照(READ_COMMITTED_SNAPSHOT)


--5.sys.dm_exec_requests 视图
--识别出阻塞链涉及到的会话、争用的资源、被阻塞会话等待了多长时间
--SELECT session_id FROM sys.dm_exec_sessions

--★ 1.sys.dm_tran_locks 视图

--(1)该动态视图可以查询出哪些资源被哪个进程ID锁了

--(2)查询出对资源授予或正在等待的锁模式

--(3)查询出被锁定资源的类型

--上面的查询语句3已经用到了这个视图,可以参考上图中的分析说明。

SELECT request_session_id AS 会话id ,
resource_type AS 请求锁定的资源类型 ,
resource_description AS 描述 ,
request_mode AS 模式 ,
request_status AS 状态
FROM sys.dm_tran_locks

--2.sys.dm_exec_connections 视图

--(1)查询出该动态视图可以查询出进程相关的信息

--(2)查询出最后一次发生读操作和写操作的时间last_read,last_write

--(3)查询出进程执行的最后一个SQL批处理的二进制标记most_recent_sql_handle

--SELECT  session_id ,
--        connect_time ,
--        last_read ,
--        last_write ,
--        most_recent_sql_handle
--FROM    sys.dm_exec_connections
 

-- dm_exec_sql_text

--(1)该函数可以将二进制标记most_recent_sql_handle作为参数,然后返回SQL代码。

--(2)阻塞进程在不断地运行,所以在代码中看到的最后一个操作不一定是导致问题的语句。在本例中最后一条执行语句是导致阻塞的语句。 

--SELECT  session_id ,
--        text
--FROM    sys.dm_exec_connections
--        CROSS APPLY sys.dm_exec_sql_text
--        (most_recent_sql_handle) AS ST

--结束会话
--KILL 52

--5.隔离级别总结

--脏读:读取未提交的更改。

--不可重复读:读操作不会在事务持续期间内保留共享锁,其他事务可以在两个读操作之间更改数据资源,读操作因而可能每次得到不同的取值。

--丢失更新:两个事务进行读操作,获得资源上的共享锁,读取完数据后,不再持有资源上的任何锁,两个事务都能更新这个值,

--    最后进行更新的事务将会覆盖其他事务做的更改,导致其他事务更改的数据丢失。

--幻读:第一次和第二次读取到的数据行数不一致。

--范围锁:读操作锁定满足查询搜索条件范围的锁

--“死锁 (Dead Lock)”的一些注意事项:

--(1)如果两个事务没有设置死锁优先级,且两个事务进行的工作量也差不多一样时,任何一个事务都有可能被终止。

--(2)解除死锁要付出一定的系统开销,因为这个过程会涉及撤销已经执行过的处理。

--(3)事务处理的时间时间越长,持有锁的时间就越长,死锁的可能性也就越大,应该尽可能保持事务简短,把逻辑上可以不属于同一个工作单元的操作移到事务以外。

--(4)上面的例子中,事务A和事务B以相反顺序访问资源,所以发生了死锁。如果两个事务按同样的顺序来访问资源,则不会发生这种类型的死锁。在不改变程序的逻辑情况下,可以通过交换顺序来解决死锁的问题。

脏数据

<wiki>从广义上看,脏数据是指没有进行过数据预处理而直接接收到的、处于原始状态的数据;
从狭义上看,是不符合研究要求,以及不能够对其直接进行相应的数据分析。
脏数据依据不同的分析目的有不同的定义,
如在常见的数据挖掘工作中,脏数据是指不完整、含噪声、不一致的数据;
而在问卷分析中,脏数据则是指不符合问卷要求的数据。

<bky>脏读dirty reads:当事务读取还未被提交的数据时,就会发生这种事件。举例来说:  

    事务a  修改了一行数据,然后   
    事务b  在   
    事务a  还未提交修改操作之前读取了被修改的行。如果   
    事务a  回滚了修改操作,那么   
    事务b  读取的数据就可以看作是从未存在过的。  

即 脏数据为还未进行保存的数据,即数据库中不存在的数据

lock 锁

1.事务中的锁

(1)SQL Server使用锁来实现事务的隔离。

(2)事务获取锁这种控制资源,用于保护数据资源,防止其他事务对数据进行冲突的或不兼容的访问。

(3) 通过锁来确保在此次事务完成之前不会有其他事务会更改此事务需要操作的数据

2.锁模式

(1)排他锁

  a.当试图修改数据时,事务只能为所依赖的数据资源请求排他锁。

  b.持有排他锁时间:一旦某个事务得到了排他锁,则这个事务将一直持有排他锁直到事务完成。

  c.排他锁和其他任何类型的锁在多事务中不能在同一阶段作用于同一个资源。

    如:当前事务获得了某个资源的排他锁,则其他事务不能获得该资源的任何其他类型的锁。其他事务获得了某个资源的任何其他类型的锁,则当前事务不能获得该资源的排他锁。

(2)共享锁

  a.当试图读取数据时,事务默认会为所依赖的数据资源请求共享锁。

  b.持有共享锁时间:从事务得到共享锁到读操作完成。

  c.多个事务可以在同一阶段用共享锁作用于同一数据资源。

  d.在读取数据时,可以对如何处理锁定进行控制。后面隔离级别会讲到如何对锁定进行控制。

3.排他锁和共享锁的兼容性

(1)如果数据正在由一个事务进行修改,则其他事务既不能修改该数据,也不能读取(至少默认不能)该数据,直到第一个事务完成。

(2)如果数据正在由一个事务读取,则其他事务不能修改该数据(至少默认不能)。

4.可锁定的资源的类型

RID、KEY(行)、PAGE(页)、对象(例如表)、数据库、EXTENT(区)、分配单元(ALLOCATION_UNIT)、堆(HEAP)、以及B树(B-tree)。
RID: 标识页上的特定行
  格式: fileid: pagenumber: rid (1:109:0 )
    其中fileid标识包含页的文件, pagenumber标识包含行的页,rid标识页上的特定行。
    fileid与sys.databases_files 目录视图中的file_id列相匹配
  例子:
    在查询视图sys.dm_tran_locks的时候有一行的resource_description列显示RID 是1:109:0 而status列显示wait,
    表示第1个数据文件上的第109页上的第0行上的锁资源。

summary

IsoLevel 是否读取未提交的行 是否不可重复读 是否丢失更新 是否幻读 共享锁持续时间 是否持有范围锁
未提交读 Y Y Y Y 当前语句 N
已提交读 N Y Y Y 当前语句 N
可重复读 N N N Y 整个事务 N
可序列化 N N N N 整个事务 Y

可重复读不会出现丢失更新。。。


https://www.cnblogs.com/jackson0714/p/TSQLFundamentals_08.html


author:monster

direction:lock

date:1/24/2019 3:12:07 PM

猜你喜欢

转载自www.cnblogs.com/monster17/p/10423311.html