`
xinklabi
  • 浏览: 1558884 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
文章分类
社区版块
存档分类
最新评论

SQL并发会出现的问题,事务隔离级别和锁机制

 
阅读更多

NOLOCKREADPAST的区别。

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 ID<>17 –不等待

 

SELECT * FROM Customer –不等待

 

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

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

 

 

HOLDLOCKTABLOCKTABLOCKX

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 CommittedRead 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 提示或未提交读隔离级别时才会进行读取操作。

 

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

分享到:
评论

相关推荐

    4种事务的隔离级别

    • 并发事务之间相互干扰,可能导致事务出现读脏,不可重复度,幻读等问题 • InnoDB实现了SQL92标准中的四种隔离级别 (1)读未提交:select不加锁,可能出现读脏; (2)读提交(RC):普通select快照读,锁select /...

    msyql锁、事务隔离级别各种场景验证测试.rar

    这些问题的本质都是数据库的多事务并发问题,为了解决多事务并发问题,数据库设计了 事务隔离机制、锁机制、MVCC多版本并发控制隔离机制 ,用一整套机制来 解决多事务并发问题。 事务及其ACID属性 事务是由一组...

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

    深入介绍了SQL Server的锁的机制,锁与事务隔离等级的关系及影响,分析了死锁的案例和解决方案。提出了锁的性能分析方法,分析并发性阻塞的问题和应用技巧。

    SQL Server事务的隔离级别

    这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。  脏读(Dirty Reads)  一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能...

    MSSQL与Oracle数据库事务隔离级别与锁机制对比

    一,事务的4个基本特征 Atomic(原子性): 事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要 么全部成功,要么全部失败。...如果不对事务进行并发控制,我们看看数据库并发操作是会有

    MySQL的Innodb中的事务隔离级别和锁的关系

     我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式。同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力。所以...

    SQL Server事务的控制与并发处理视频

    SQL Server事务的控制与并发处理,讲述了基本的事务的处理流程,设置隔离级别避免脏读,不可重复读和幻读

    简述MySql四种事务隔离级别

    在SQL标准中定义了四种隔离级别, 每一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。 下面简单地介绍一下四种隔离级别。 1.READ ...

    mysql的事务,隔离级别和锁用法实例分析

    本文实例讲述了mysql的事务,隔离级别和锁用法。分享给大家供大家参考,具体如下: 事务就是一组一起成功或一起失败的sql语句。事务还应该具备,原子性,一致性,隔离性和持久性。 一、事务的基本要素 (ACID) 1、...

    通过实例分析MySQL中的四种事务隔离级别

    在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。数据库事务的隔离级别有4个,下面话不多说了,来一起看看详细的介绍吧。 数据库事务有四种隔离级别: 未提交读(Read Uncommitted):允许脏...

    MySQL中Innodb的事务隔离级别和锁的关系的讲解教程

    我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式。同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力。所以对于...

    高并发情况下,MYSQL的锁等待问题分析和解决方案

    事务隔离级别 参考文章《事务的ACID特性》 共享锁(S锁) SELECT 语句时对查询行加的锁类型为共享锁。 共享锁的特性为:不允许其他事务对该记录加排他锁,但是允许加共享锁。 保持时间:可重复度级别中共享锁会保持...

    数据库锁(行锁,表锁,共享锁,排他锁)脏读、不可重复读、幻读和事物隔离级别

    3.锁冲突概率低,并发性高,但是会有死锁的情况出现。 表锁 顾名思义,表锁就是一锁锁一整张表,在表被锁定期间,其他事务不能对该表进行操作,必须等当前表的锁被释放后才能进行操作。表锁响应的是非索引字段,即...

    Java面试Mysql.pdf

    事务的隔离级别? 怎么优化数据库 SQL优化 大表数据查询,怎么优化 常用的聚合函数 13. 百万级别或以上的数据如何删除 锁 对MySQL的锁了解吗 隔离级别与锁的关系 按照锁的粒度分数据库锁有哪些?锁机制与InnoDB锁...

    SQL 事务与锁 详解

    本篇博客旨在记录数据库中事务与锁机制的必要性,记录了如何在数据库中使用事务与锁机制实现数据库的一致性以及并发性。 文章目录1. 事务机制1.1. 事务是什么1.2. 事务的必要性1.3.... 事务的隔离级别与并发问题3.

    57 停一停脚步:梳理一下数据库的多事务并发运行的隔离机制l.pdf

    57 停一停脚步:梳理一下数据库的多事务并发运行的隔离机制l.pdf

    JDBC专题(六)-JDBC专题-事务的隔离级别.docx

    •隔离性(Isolation) 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。 A ------&gt; B B ------&gt; C •持久性(Durability...

    MySQL之锁和事务

    目录一、锁分类死锁二、事务事务特性隔离级别多版本并发控制MVCC 一、锁 分类 Mysql为了解决并发、数据安全的问题,使用了锁机制。可以按照锁的粒度把数据库锁分为表级锁和行级锁。 表级锁 对当前操作的整张表加锁,...

    (mysql面试题)MySQL中的事务和锁的概念及其作用及代码展示.txt

    事务是一个不可分割的工作单位,它包含了一系列的SQL语句和操作。事务具有以下四个特性,通常称为ACID特性: - 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败回滚; - 一致性(Consistency)...

    19-事务-源代码.rar

    五、事务的特性和隔离级别(概念性问题---面试)。 1.什么是事务 2.mysql的事务 1.QueryRunner 1.事务的特性ACID 2.并发访问问题----由隔离性引起 3.事务的隔离级别 默认是自动事务: 执行sql语句:...

Global site tag (gtag.js) - Google Analytics