zoukankan      html  css  js  c++  java
  • SQL Server 中WITH (NOLOCK)

    with(nolock)的功能:

    1: 指定允许脏读。不发布共享锁来阻止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻碍当前事务读取锁定数据。允许脏读可能产生较多的并发操作,但其代价是读取以后会被其他事务回滚的数据修改。这可能会使您的事务出错,向用户显示从未提交过的数据,或者导致用户两次看到记录(或根本看不到记录)。有关脏读、不可重复读和幻读的详细信息,请参阅并发影响。

    2: READUNCOMMITTED 和 NOLOCK 提示仅适用于数据锁。所有查询(包括那些带有 READUNCOMMITTED 和 NOLOCK 提示的查询)都会在编译和执行过程中获取 Sch-S(架构稳定性)锁。因此,当并发事务持有表的 Sch-M(架构修改)锁时,将阻塞查询。例如,数据定义语言 (DDL) 操作在修改表的架构信息之前获取 Sch-M 锁。所有并发查询(包括那些使用 READUNCOMMITTED 或 NOLOCK 提示运行的查询)都会在尝试获取 Sch-S 锁时被阻塞。相反,持有 Sch-S 锁的查询将阻塞尝试获取 Sch-M 锁的并发事务。有关锁行为的详细信息,请参阅锁兼容性(数据库引擎)。

    3: 不能为通过插入、更新或删除操作修改过的表指定 READUNCOMMITTED 和 NOLOCK。SQL Server 查询优化器忽略 FROM 子句中应用于 UPDATE 或 DELETE 语句的目标表的 READUNCOMMITTED 和 NOLOCK 提示。

    这个东西是有利有弊,

    使用with(nolock)时查询不受其他排它锁阻塞

    举个例子:模拟事务正在进行
    打开回话一:执行

    SELECT @@spid查看会话ID --查询当前会话


    BEGIN TRAN

    UPDATE TEST SET NAME='Timmy' WHERE ID =1;

    --ROLLBACK -- 不提交也不回滚
    打开回话二:执行
    SELECT * FROM TEST;

    打开回话三查询阻塞情况:
    SELECT wt.blocking_session_id AS BlockingSessesionId
    ,sp.program_name AS ProgramName
    ,COALESCE(sp.LOGINAME, sp.nt_username) AS HostName
    ,ec1.client_net_address AS ClientIpAddress
    ,db.name AS DatabaseName
    ,wt.wait_type AS WaitType
    ,ec1.connect_time AS BlockingStartTime
    ,wt.WAIT_DURATION_MS/1000 AS WaitDuration
    ,ec1.session_id AS BlockedSessionId
    ,h1.TEXT AS BlockedSQLText
    ,h2.TEXT AS BlockingSQLText
    FROM sys.dm_tran_locks AS tl
    INNER JOIN sys.databases db
    ON db.database_id = tl.resource_database_id
    INNER JOIN sys.dm_os_waiting_tasks AS wt
    ON tl.lock_owner_address = wt.resource_address
    INNER JOIN sys.dm_exec_connections ec1
    ON ec1.session_id = tl.request_session_id
    INNER JOIN sys.dm_exec_connections ec2
    ON ec2.session_id = wt.blocking_session_id
    LEFT OUTER JOIN master.dbo.sysprocesses sp
    ON SP.spid = wt.blocking_session_id
    CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
    CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
    打开会话四:执行

    SELECT * FROM TEST WITH(NOLOCK)--会发现数据马上出来

    这是由于加了with(nolock)会话一事务设置的排他锁不会阻碍当前事务读取锁定数据,所以会话四不会被阻塞

    但是:假如由于某种原因,该事务回滚了, SELECT * FROM Book AS b WHERE b.BookName = 'Timmy' AND b.ID = 1 查询到的这边数据就是一条脏数据,又叫无效数据的读出,是指在数据库访问中,事务T1将某一直修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致T2所读取到的数据是无效的


    所以with(nolock)是有利有弊的
    大体使用场景:

    基础数据表,这些表变更较少
    历史数据库修改较少
    业务允许出现脏读的情况
    数据量超大的表,出于性能考虑,而允许脏读

    看下这三个区别:
    SELECT * FROM TEST NOLOCK -- nolock起到了表的别名的作用

    SELECT * FROM TEST (NOLOCK);

    SELECT * FROM TEST WITH(NOLOCK);

    (NOLOCK)与WITH(NOLOCK)其实功能上是一样的,但08版本就不推荐省略with

    在使用链接服务器的SQL当中,(NOLOCK)不会生效,WITH(NOLOCK)才会生效

  • 相关阅读:
    病魔带来的礼物
    不可深交者
    做事情
    Maven-7:Maven配置编译的字符集方法
    maven打包可以行文件,包含依赖包等
    Maven打包可执行Jar的几种方法
    maven项目打包时生成dependency-reduced-pom.xml
    【Maven】maven打包生成可执行jar文件
    【Maven学习】Maven打包生成包含所有依赖的jar包
    【Maven学习】Maven打包生成普通jar包、可运行jar包、包含所有依赖的jar包
  • 原文地址:https://www.cnblogs.com/niuzaihenmang/p/5590385.html
Copyright © 2011-2022 走看看