sqlserver中的锁/事务/隔离级别

SQL Server——SQL Server触发器及事务和锁 一、触发器 触发器(trigger)是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表 事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,当对一个表 进行操作( insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务 规则等。 触发器可以从 DBA_TRIGGERS ,USER_TR... 阅读详情

sqlserver中的锁
共享锁(s)/更新锁(U)/排它锁(独占锁X)

共享 (S) 锁允许并发事务读取 (SELECT) 一个资源。资源上存在共享 (S) 锁时,任何其它事务都不能修改数据。
更新 (U) 锁可以防止通常形式的死锁。若要避免这种潜在的死锁问题,请使用更新 (U) 锁。一次只有一个事务可以获得资源的更新 (U) 锁。
如果事务修改资源,则更新 (U) 锁转换为排它 (X) 锁。否则,锁转换为共享锁。
排它 (X) 用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。
排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能读取或修改排它 (X) 锁锁定的数据

增删改查使用:

SELECT 语句在默认隔离级别下会产生共享锁,该锁查询完就释放,不需要等待所在的事务提交。
UPDATE 语句先使用更新锁锁定数据,然后升级成独占锁(事务级别,非命令级别)
INSERT,UPDATE,DELETE 语句使用独占锁

UPDLOCK.UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。
当我们用UPDLOCK来读取记录时可以对取到的记录加上更新锁,从而加上锁的记录在其它的线程中是不能更改的只能等本线程的事务结束后才能更改.
测试:
在另一个查询里:

updlock/TABLOCKX(如果添加transaction则是事务级别,非命令级别)(Shared Lock是命令级别,即使添加transaction)
BEGIN TRANSACTION
SELECT * FROM myTable WITH (UPDLOCK) WHERE Id in (1,2,3)
waitfor delay '00:00:10'
update myTable set [Name]='ZZ' where Id in (1,2,3)
commit TRANSACTION

在另一个查询里:
SELECT * FROM myTable WHERE Id in (1,2,3)

可以马上查询到数据。
但如果要更新数据,必须等其他更新锁释放后才能执行。

update myTable set [Name]='ZZ' where Id in (1,2,3)

这就说明,有时候需要控制某条记录在我读取后就不许再进行更新,那么我就可以将所有要处理当前记录的查询都加上更新锁,以防止查询后被其它事务修改.将事务的影响降低到最小

select * from dbo.Employee with(holdlock); with关键字来设置锁表的方式。
NOLOCK(不加锁)
NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别

UPDLOCK(修改锁 IX)此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务(事务级别,非命令级别)或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。

HOLDLOCK 持有共享锁,直到整个事务完成,应该在被锁对象不需要时立即释放,等于SERIALIZABLE事务隔离级别
HOLDLOCK(保持锁 S)此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。
TABLOCK(表锁 S)此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。

TABLOCKX(排它表锁 X)此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。


ROWLOCK(IS)此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。
PAGLOCK(页锁 IS)此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。

READPAST 让sql server跳过任何锁定行,执行事务,适用于READ UNCOMMITTED事务隔离级别只跳过RID锁,不跳过页,区域和表锁
ROWLOCK 强制使用行锁

行锁使用注意事项
1、ROWLOCK行级锁确保在用户取得被更新的行,到该行进行更新,这段时间内不被其它用户所修改
因而行级锁即可保证数据的一致性,又能提高数据操作的并发性。
2、ROWLOCK告诉SQL Server只使用行级锁,ROWLOCK语法可以使用在SELECT,UPDATE和DELETE语句中。
3、ROWLOCK指定通常采用页锁或表锁时,采用行锁。 在从 SNAPSHOT 隔离级别操作的事务中指定时,
除非将 ROWLOCK 与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合,否则不会取得行锁。
4、UPDLOCK指定采用更新锁并保持到事务完成。UPDLOCK 仅对行级别或页级别的读操作采用更新锁。 
如果将 UPDLOCK 与 TABLOCK 组合使用或出于一些其他原因采用表级锁,将采用排他 (X) 锁。
指定 UPDLOCK 时,忽略 READCOMMITTED 和 READCOMMITTEDLOCK 隔离级别提示。 
例如,如果将会话的隔离级别设置为 SERIALIZABLE 且查询指定 (UPDLOCK, READCOMMITTED),则忽略 READCOMMITTED 提示且使用 SERIALIZABLE 隔离级别运行事务。
5、HOLDLOCK等同于SERIALIZABLE。HOLDLOCK 仅应用于那些为其指定了 HOLDLOCK 的表或视图,
并且仅在使用了 HOLDLOCK 的语句定义的事务的持续时间内应用。 HOLDLOCK 不能被用于包含 FOR BROWSE 选项的 SELECT 语句。
ROWLOCK告诉 SQL  Server只使用行级锁。ROWLOCK语法可以使用在SELECT, UPDATE和DELETE语句中,不过 我习惯仅仅在UPDATE和DELETE语句中使用。
如果在UPDATE语句中有指定的主键,那么就总是会引发行级锁的。但是当SQL  Server对几个这种UPDATE进行批处理时,某些数据正好在同一个页面(page),
这种情况在当前情况下  是很有可能发生的,这就象在一个folder中,创建一个新文件需要较长的时间,而同时你又要去更新该folder中的某些文件。当页面锁引发后,
事情就开始变得糟糕了。而如果在UPDATE或者DELETE 时,没有指定主键,数据库当然认为很多数据会收到影响,那样 就会直接引发页面锁,事情同样变得糟糕
通过指定使用行级锁,这种情况可以得到避免。但是需要小心的是,如果你错误地使用在过多行上,数据库并不会聪明到自动将行级锁升级到页面锁,服务器也会因为行级锁的开销而消耗大量的内存和CPU,直至无法响应。尤其主要留意的是 企业管理器中"管理/当前活动"(Management /Current  Activity)这一项。该项会花较长的时间来载入锁的信息。这些信息是十分有用的,当你使用行级锁后,你如果在"锁/处理" (Locks/Processes)下看到几百个锁,一点都不奇怪,而恰恰应该庆幸锁超时和死锁的问题减少了。   

锁的分类
1.按锁定的对象来分
有表锁、行锁、数据库锁等,表锁定是对整个表进行锁定,行锁定是对表中特定行进行锁定,数据库锁是锁定整个数据库。

2.从数据库系统角度分为三种:
排他锁、共享锁、更新锁。

3.从程序员角度分为两种:
一种是悲观锁,一种乐观锁

悲观锁(Pessimistic Lock)
传统的关系数据库里用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在操作之前先上锁。
共享锁(Share Lock)

S锁,也叫读锁,用于所有的只读数据操作。共享锁是非独占的,允许多个并发事务读取其锁定的资源。
性质
1. 多个事务可封锁同一个共享页;
2. 任何事务都不能修改该页;
3. 通常是该页被读取完毕,S锁立即被释放。

在SQL Server中,默认情况下,数据被读取后,立即释放共享锁。
例如,执行查询语句“SELECT * FROM my_table”时,首先锁定第一页,读取之后,释放对第一页的锁定,然后锁定第二页。这样,就允许在读操作过程中,修改未被锁定的第一页。
例如,语句“SELECT * FROM my_table HOLDLOCK”就要求在整个查询过程中,保持对表的锁定,直到查询完成才释放锁定。

排他锁(Exclusive Lock)

X锁,也叫写锁,表示对数据进行写操作。如果一个事务对对象加了排他锁,其他事务就不能再给它加任何锁了。(某个顾客把试衣间从里面反锁了,其他顾客想要使用这个试衣间,就只有等待锁从里面打开了。)
性质
1. 仅允许一个事务封锁此页;
2. 其他任何事务必须等到X锁被释放才能对该页进行访问;
3. X锁一直到事务结束才能被释放。

产生排他锁的SQL语句如下:select * from ad_plan for update;

更新锁

U锁,在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。

因为当使用共享锁时,修改数据的操作分为两步:
1. 首先获得一个共享锁,读取数据,
2. 然后将共享锁升级为排他锁,再执行修改操作。
这样如果有两个或多个事务同时对一个事务申请了共享锁,在修改数据时,这些事务都要将共享锁升级为排他锁。这时,这些事务都不会释放共享锁,而是一直等待对方释放,这样就造成了死锁。
如果一个数据在修改前直接申请更新锁,在数据修改时再升级为排他锁,就可以避免死锁。

性质
1. 用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;
2. 当被读取的页要被更新时,则升级为X锁;
3. U锁判断不符合条件就释放,符合就转为X锁。

悲观锁按作用范围划分为:行锁、表锁。(这部分摘自https://www.jianshu.com/p/eb41df600775 )

行锁
锁的作用范围是行级别。

表锁
锁的作用范围是整张表。

数据库能够确定那些行需要锁的情况下使用行锁,如果不知道会影响哪些行的时候就会使用表锁。

举个例子,一个用户表user,有主键id和用户生日birthday。
当你使用update … where id=?这样的语句时,数据库明确知道会影响哪一行,它就会使用行锁;
当你使用update … where birthday=?这样的的语句时,因为事先不知道会影响哪些行就可能会使用表锁。


sqlserver中的隔离级别
SQL Server

的四种隔离级别知识点整理,特别制作了流程图,⽅便以后查看!

SET TRANSACTION ISOLATION LEVEL
{ 
READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ 相当于(HOLDLOCK)):
| SERIALIZABLE 它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。
} 
未提交读READ UNCOMMITTED(脏读)相当于with(nolock)
演示: 
1)用户B:BEGIN TRAN 
UPDATE test SET age=25 WHERE name = ‘AA’
2)用户A: 
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED(此句不写即默认为READ COMMITTED模式)
SELECT * FROM test(此时将查到AA的age值为25)
3)用户B: ROLLBACK
(此时撤消了步骤1的UPDATE操作,则⽤户A读到的错误数据被称为脏读)

提交读(READ COMMITTED)
意义:指定在读取数据时控制共享锁以避免脏读。此隔离等级的主要作⽤是避免脏读。

1)用户B:BEGIN TRAN 
UPDATE test SET age=25 WHERE name = ‘AA’
2)用户A: SET TRANSACTION ISOLATION LEVEL READ COMMITTED 
SELECT * FROM test (上句设置了提交读模式,则此时将会查不到数据,显示查询等待中,直到用户B进行了ROLLBACK或者COMMIT操作后,此语句才会生效) 

三、不⼀致的分析
REPEATABLE READ(重复读) 
意义:在多用户环境下,用户A开了一个事务,并且先对test表的某条记录做了查询(select * from test where name = ‘AA’),
接着用户B对test表做了更新并提交(update test set age=25 where name=’AA’)
,这时A再去查test表中的这条记录,第一次读到的age值为12,第二次为25,两次读到的数据不一样,称之为重复读。(如图演⽰) 


SERIALIZABLE事务隔离级别
排它锁不受隔离级别控制,共享锁受隔离级别控制
结论如下:
在任何隔离级别下,事务在执行写操作时都申请排它锁(exclusive lock),持有排它锁直到事务结束,排它锁不受隔离级别的控制;
而共享锁(Shared Lock)受到隔离级别的控制,隔离级别影响Shared Lock的申请和释放:
在 Read Uncommitted隔离级别下,读操作不会申请Shared Lock;
在 Read Committed(不使用row-versioning),Repeatable Read 和 Serializable隔离级别下,都会申请Shared Lock;
在 Read Committed(不使用row-versioning) 隔离级别下,在读操作执行时,申请和持有Share Lock;一旦读操作完成,释放Shared Lock;
在 Repeatable Read 和 Serializable隔离级别下,事务会持有Shared Lock,直到事务结束(提交或回滚);
在Serializable隔离级别下,事务会持有范围Shared Lock(Range Lock),锁定一个范围,在事务活跃期间,其他事务不允许在该范围中进行更新(Insert 或 delete)操作;

SQLServer默认隔离级别: Read Committed.
更新锁和更新锁互斥。共享锁和和共享锁可以共享。共享锁和和更新锁可以共享。排它锁独占。
SQLServer隔离级别只会影响共享锁。
事务(可以是数据库事务,可以是程序事务)在执行写操作时都申请排它 (X) 锁(exclusive lock),持有排它锁直到事务结束,排它锁不受隔离级别的控制;

事务的分类 (分类)

事务分为三类:显式事务、隐式事务、自动提交事务
(1) 显式事务:用 begin transaction 明确指定事务的开始,由 commit transaction 提交事务、rollback transaction 回滚事务到事务结束。
(2) 隐式事务:通过设置 set implicit_transactions on 语句,将隐式事务模式设置为打开。
当以隐式事务模式操作时,不必使用 begin transaction 开启事务,当一个事务结束后,这个模式会自动启用下一个事务,
只需使用 commit transaction 提交事务或 Rollback Transaction 回滚事务即可。
(3) 自动提交事务: 这是 SQL Server 的默认模式,它将每条单独的 T-SQL 语句视为一个事务。如果成功执行,则自动提交。如果错误,则自动回滚。

如何防止死锁
表设计:
1 尽可能使用分区表,把数据放到不同的文件中,尽可能以分区表或分区视图的方式拆分包含大量数据的表,
将它们保存在不同的物量磁盘和文件组中。在访问数据时,可以分散访问保存在不同分区的数据,从而减少因为在大型表中放置锁而造成其它事务长时间等待的概率
2横向分割表设计,将表按照某种原则(可按照字段读写频率来设计)设计成相对应的几个表,之间采用主(外)键关联;
3 使用较低的隔离级别,尽可能地为用户连接指定具有最少限制的事务隔离级别,而不是总是使用默认的READ COMMITTED
    对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select * from tableA(nolock)
4 对于频繁使用的表使用集簇化的索引;
5 减少数据库并发量,死锁是由于并发访问数据库资源造成的,减少死锁就应该限制应用系统的并发访问量。我们应该合理设置后台服务的线程数,

update/delete/insert
1 将大量数据的操作分解,分步骤,分阶段的执行。也应该避免在用户量大的时候大规模的进行后台数据库操作,应该将大规模的数据库操作放在用户量最少的时候进行。
2设法让UPDATE和DELETE语句使用索引;
    
select
1 select 会获取共享锁,进而会让排它锁等待,所以查询时要添加where条件或者top N限制


事务:
1 按照同一顺序访问数据库资源,(A 先访问tb1,再访问tb2,B先访问tb1,再访问tb2)
2 保持事务时间短,如果可能的话,应将较复杂的事务分割成多个较简单的事务
3 所有条件逻辑、变量赋值以及其他相关的预备设置操作应当在事务之外完成,而不应该放到事务之内。永远不要为了接受用户输入而暂停某个事务,用户输入应当总是在事务之外完成
4 能够在死锁出现并中止用户事务之后,以随机的时间间隔自动重新提交事务。这里等待时间的随机性非常重要,这是因为另一个竞争的事务也可能在等待,
我们不应该让两个竞争的事务等待同样的时间,然后再在同一时间执行它们,这样的话将导致新的死锁。


10 如果客户程序需要先用一定的时间检查数据,然后可能更新数据,也可能不更新数据,那么最好不要在整个记录检查期间都锁定记录。
假设大部分时间都是检查数据而不是更新数据,那么处理这种特殊情况的一种方法就是:先选择出记录(不加UPDATE子句。
UPDATE子句将在记录上加上共享锁),然后把它发送给客户。
如果用户只查看记录但从来不更新它,程序可以什么也不做;反过来,如果用户决定更新某个记录,
那么他可以通过一个WHERE子句检查当前的数据是否和以前提取的数据相同,然后执行UPDATE。
类似地,我们还可以检查记录中的时间标识列(如果它存在的话)。如果数据相同,则执行UPDATE操作;如果记录已经改变,则应用应该提示用户以便用户决定如何处理。
虽然这种方法需要编写更多的代码,但它能够减少加锁时间和次数,提高应用的整体性能。

11 使用游标会降低并发性。为避免这一点,如果可以使用只读的游标则应该使用READ_ONLY游标选项,否则如果需要进行更新,
尝试使用OPTIMISTIC游标选项以减少加锁。设法避免使用SCROLL_LOCKS游标选项,该选项会增加由于记录锁定引起的问题。
12使用sp_who和sp_who2来确定可能是哪些用户阻塞了其他用户


9. 数据设计时,尽量避免 update/delete. 举例来说,如果是一个请假条的审批流程,
把请假条申请设计成一个表,领导批复设计成另一个表。尽量避免设计时合并成一个表,
把批准状态(同意/否决)、批准时间当成“请假条申请”的属性。
说极端一点,最好从数据库设计上,避免后续编程有 update/delete, 只有 insert。 好像现在流行的 NoSQL 也是这么个思路。


7 设置锁超时时间,一但超时,阻塞语句自动取消,释放资源,报1222错误,但当天事务报错,不会回滚,会造成数据错误,要手工处理

查看超时时间
select @@lock_timeout (-1)
set @@lock_timeout=0
select @@TRANCOUNT
@@error代表最近的一个T-SQL语句的报错号
select @@MAX_CONNECTIONS
并发数

查看锁活动情况
select * from sys.dm_tran_locks
select object_name(resource_associated_entity_id),* from sys.dm_tran_locks 
where resource_type='object' and object_name(resource_associated_entity_id)='test222'
查看事务活动情况
dbcc opentran


10亿表如何更新500W数据,一次只能更新5000
1 run in un business time
2 分批次跑,一次跑5000行左右,每次commit,要添加try catch ,try 中加transaction/commit catch中加rollcack
3 对表用行级锁
4可以建个临时表,表中有ID和要更新列,然后用临时表update target表

聚集索引和非聚集索引区别
SQL SERVER中索引类型包括的三种类型分别是
唯一索引(UNIQUE),聚集索引(CLUSTERED) ,非聚集索引(NONCLUSTERED)
主键与唯一索引的区别
主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。 主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。 唯一性索引列允许空值,而主键列不允许为空值。 主键列在创建时,已经默认为空值 + 唯一索引了。

对一个大表(5亿)添加两列数据
phone char(11) 手机号 (如果用alter方式的话里面也是存储的NULL,建表也很快,但是char会占用空间,即使是NULL值也占用空间 )
 这种方式可以再单独设计一个表,然后里面存储phone char(11),然后两张表中存共同的ID号
address nvarchar(100) 可以用alter table add column address nvarchar(100),这种方式不会对历史数据行赋值(全部为null)

执行计划怎么看
表扫描方式(全表,索引)
join方式
是否用了索引

1、越粗表示扫描影响的行数愈多。
2、Actual Number of Rows  扫描中实际影响的的行数。
3、Estimated Number of Rows 预估扫描影响的行数。
4、Estimated row size 操作符生成的行的估计大小(字节)。
5、Estimated Data Size 预估影响的数据的大小。


char/varchar/nvarchar区别
Hint主要分为三类应用:查询Hint、表Hint、连接Hint

查询Hint
{ HASH | ORDER } GROUP
HASH GROUP
HASH JOIN也好,HASH GROUP也好,HASH都是我认为可能还存在使用场景的。因为从过往经验看,
优化器容易选择错误(造成性能大幅下降)的还是排序或者循环,这个对资源消耗是最大的,那么HASH对于查询是有大表参与的情况下是相对比较友好的。


TABLE HINT(table,INDEX(索引名), FORCESEEK)
指定查询使用某个表索引,FORCESEEK要求使用检索而不是表扫描
HOLDLOCK|NOLOCK|READPAST|ROWLOCK|TABLOCK|XLOCK
这几个可能是和锁有关的几个提示可能会用到的。HOLDLOCK主要是用到存储过程事务里面,先对表加锁后一直到事务提交,
SELECT查询用到。NOLOCK再常见不过。像生产环境查询表数据通常加NOLOCK避免造成堵塞影响生产上的查询,另外一个就是ETL抽数据也是加NOLOCK。
REAPAST的使用场景是对于超高并发下更新数据,跳过已经加了锁的行而取下一行。这个就是电商的秒杀场景或者取号场景。ROWLOCK也是针对高并发更新数据场景,
对行级别加锁而避免SQL SERVER对表级别加锁。TABLOCK就是相反,加表锁是当前事务会在多处对数据进行更新,避免更新完后后面有其他的并发事务更新了表的行
(如果不加表锁,前面的数据更新是采用页锁或者行锁,但是这样子会影响当前存储过程事务在后面对表的二次更新的数据结果,就需要加表锁。)。
TABLOCK另外一个变体是TABLOCKX,这个是直接排他,就是其他连接连表数据都不能查询,直接堵塞其他对表的查询请求。XLOCK是最高级别的锁,
直接排他,指定XLOCK要同时指定ROWLOCK, PAGLOCK 或 TABLOCK。
FROM t WITH (TABLOCK, INDEX(myindex))  

连接Hint: merge/hash/nest loop/
table  with(nolock)
index hint


表变量和临时表

临时表
它存储在Tempdb中,显示删除(DROP)或连接断开时数据才会被删除。

本地临时表:以#为前缀,只对本地当前的用户连接可见,连接断开时被删除。
全局临时表:以##为前缀,对所有用户可见,当所有引用该表的用户断开连接时被删除。
表变量
表变量在批处理结束后自动被删除

本地表变量:以@为前缀
全局表变量:以@@为前缀,一般都是系统的全局变量,如:@@Error、@@RowCount
表变量和临时表的区别
表变量是存储在内存中,不产生日志
表变量不允许有非聚集索引
表变量是不允许有默认值,也不允许有约束
临时表中是有锁的机制,表变量没有
表变量存放在内存中,正是因为这一点所有用户访问表变量的时候SQL Server是不需要生成日志。
表变量创建的语法类似于临时表,区别就在于创建的时候,必须要为之命名。表变量是变量的一种,
表变量也分为本地及全局的两种,本地表变量的名称都是以“@”为前缀,只有在本地当前的用户连接中才可以访问。全局的表变量的名称都是以“@@”为前缀,
一般都是系统的全局变量,像我们常用到的,如@@Error代表错误的号,@@RowCount代表影响的行数。

表变量的行为类似于局部变量,有明确定义的作用域。该作用域为声明该变量的函数、存储过程或批处理。
在其作用域内,表变量可像常规表那样使用。该变量可应用于 SELECT、INSERT、UPDATE 和 DELETE 语句中用到表或表的表达式的地方。但是,表不能用在下列语句中:
INSERT INTO table_variable EXEC 存储过程。
SELECT select_list INTO table_variable 语句。
在定义表变量的函数、存储过程或批处理结束时,自动清除表变量。
表类型声明中的 CHECK 约束、DEFAULT 值和计算列不能调用用户定义函数。
在存储过程中使用表变量与使用临时表相比,减少了存储过程的重新编译量。
涉及表变量的事务只在表变量更新期间存在。这样就减少了表变量对锁定和记录资源的需求。
不支持在表变量之间进行赋值操作。
declare @t1 table(t1 int)
declare @t2 table(t2 int)
set @t1=@t2 –错误
另外,由于表变量作用域有限,并且不是持久数据库的一部分,因而不受事务回滚的影响。
临时表:
临时表与永久表相似,只是它的创建是在Tempdb中,它只有在一个数据库连接结束后或者由SQL命令DROP掉,才会消失,否则就会一直存在。临时表在创建的时候都会产生SQL Server的系统日志,虽它们在Tempdb中体现,是分配在内存中的,它们也支持物理的磁盘,但用户在指定的磁盘里看不到文件。

  临时表分为本地和全局两种,本地临时表的名称都是以“#”为前缀,只有在本地当前的用户连接中才是可见的,当用户从实例断开连接时被删除。全局临时表的名称都是以“##”为前缀,创建后对任何用户都是可见的,当所有引用该表的用户断开连接时被删除
用法:
表变量:无表关联操作,只作为中间集进行数据处理;临时表:有表关联,且不能确定数据量大小的情况下。理论如此,真正用法要按照实际项目需求而定。
如何分析定位问题

create table test222
(id int,
name varchar(10)
,phone char(11))

drop table test222
create table test222
(id int,
name varchar(10)
)

insert into test222 values(1,'11')
insert into test222 values(2,'22')
insert into test222 values(3,'33')

select * ,len(phone) from test222
alter table test222 add phone char(11)
alter table test222  add address nvarchar(100)

关于数据库表的主键设计,一般而言,是根据业务需求情况,以业务逻辑为基础,形成主键。

比如,销售时要记录销售情况,一般需要两个表,一个是销售单的概要描述,记录诸如销售单号、总金额一类的情况,
另外一个表记录每种商品的数量和金额。对于第一个表(主表),通常我们以单据号为主键;对于商品销售的明细表(从表),
我们就需要将主表的单据号也放入到商品的明细表中,使其关联起来形成主从关系。同时该单据号与商品的编码一起,形成明细表的联合主键。
这只是一般情况,我们稍微将这个问题延伸一下:假如在明细中,我们每种商品又可能以不同的价格方式销售。有部分按折扣价格销售,有部分按正常价格销售。
要记录这些情况,那么我们就需要第三个表。而这第三个表的主键就需要第一个表的单据号以及第二个表的商品号再加上自身需要的信息一起构成联合主键;
又或者其他情况,在第一个主表中,本身就是以联合方式构成联合主键,那么也需要在从表中将主表的多个字段添加进来联合在一起形成自己的主键。

解决方案
从上面,我们已经看到现有结构存在着相当多的弊端,主要是导致程序复杂、效率降低并且不利于分页。
为解决上述问题,本文提出:当应用系统后台数据库表间存在主从关系时,数据库表额外增加一非业务字段作为主键,该字段为数值型;或者当该表需要在应用中进行分页查询时,也应考虑如此设计。一般地,我们也可以几乎为任何表增加一个与业务逻辑无关的字段作为该表的主键字段。
由于该字段要作为表的主键,那么其首要条件是要保证在该表中要具有唯一性。

SQLServer事务的隔离级别 SQLServer事务的隔离级别 数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况。 更新丢失(Lost update)   两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。 脏读(Dirty Reads)   一个事务开始读取了某行数据,但是另外一个事务已经... 阅读详情

相关推荐

[MSSQL]SQLServer之数据库行锁

行锁使用注意事项 1、ROWLOCK行级锁确保在用户取得被更新的行,到该行进行更新,这段时间内不被其它用户所修改。因而行级锁即可保证数据的一致性,又能提高数据操作的并发性。 2、ROWLOCK告诉SQL Server只使用行级锁,ROWLOCK语法可以使用在SELECT,UPDATE和DELETE语句中。 3、ROWLOCK指定通常采用页锁或表锁时,采用行锁。 在从 SNAPSHOT 隔离级别操作的事务中指定时,除非将 ROWLOCK 与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合,

德仔 3252

SQLServer共享锁,更新锁,排它锁,死锁,默认隔离级别

互斥锁不受隔离级别控制,共享锁受隔离级别控制 结论如下: 在任何隔离级别下,事务在执行写操作时都申请互斥锁(exclusive lock),持有互斥锁直到事务结束,互斥锁不受隔离级别的控制;而共享锁(Shared Lock)受到隔离级别的控制,隔离级别影响Shared Lock的申请和释放: 在 Read Uncommitted隔离级别下,读操作不会申请Shared Lock; 在 Read Committed(不使用row-versioning),Repeatable Read 和 Serializa

weixin_46879188的博客 5852

基于Codex与Skills的学术研究自动化全流程实战指南

还在为海量文献下载、整理、阅读和综述写作而头疼吗?面对堆积如山的PDF,你是否感到无从下手?从选题、文献检索、到写作、绘图、润色,再到应对AI检测和审稿意见,学术研究的每一步都充满挑战。本文将为你带来一套堪称“王炸组合”的解决方案: Codex + Skills 。这不是简单的工具介绍,而是一套从零开始,覆盖学术研究全流程的保姆级实战教程。我们将手把手教你如何安装、配置,并利用强大的Skills(技能)自动化处理文献下载管理、高效撰写综述、生成专业图表、智能润色降重,直至应对审稿。无论你是科研新手还是希望提

weixin_29041195的博客 765

sqlserver 事务和锁详解

事务的概念 事务( transacton)是构成单一逻辑工作单元的操作集合,它是一个SQL语句序列,通常,每个 INSERT UPDATE、 DELETE命令被作为一个事务处理,事务开始之后,所有的操作都陆续写到事务日志中,因此事务处理确保了数据的一致性和可恢复性 当进行事务操作时,系统自动生成一个检查点机制,检査点周期地楹査事务日志,如果在事务日志中事务全部完成,那么检査点将事务日志中的该...

羽之大公公的博客 3307

Anaconda下安装LabelImg

Anaconda下安装LabelImg

LYH8543的博客 756

从平衡车到寻迹小车:IMU963RA九轴陀螺仪实战避坑与四元数融合指南

本文详细解析了IMU963RA九轴陀螺仪在机器人姿态控制中的应用,重点探讨了从六轴升级到九轴系统的技术路径及四元数融合算法。通过实战案例,揭示了如何利用地磁计补偿陀螺积分漂移,并提供硬件集成、传感器校准及算法实现的完整解决方案,有效将8小时漂移控制在2度以内。

weixin_27219587的博客 254

mysql,oracle,sql server中的默认事务隔离级别查看,更改

第一节 好久没碰数据库了,只是想起自己当时在搞数据库的时候在事务隔离级别这块老是卡,似懂非懂的。现在想把这块整理出来,尽量用最简洁的语言描述出来,供新人参考。 首先创建一个表account。创建表的过程略过(由于InnoDB存储引擎支持事务,所以将表的存储引擎设置为InnoDB)。表的结构如下: 表结构 然后往表中插入两条数据,插入后结果如下: 数据 为了说明问题,我们打开两个...

Alex的博客 1万+

Python实战:3种高效方法将txt转csv(附pandas对比测试)

本文针对Python中将txt文件转换为csv格式的需求,深度评测了open()、csv模块和pandas三种主流方法。通过详尽的性能对比测试,从执行效率、内存占用和适用场景等维度提供选型指南,帮助开发者根据数据规模与复杂度选择最高效的转换方案。

weixin_29073241的博客 263

SqlServer事务详解(事务隔离性和隔离级别详解)

概述   不少人对于事务的使用局限于begin transaction:开始事务、commit transaction:提交事务、rollback transaction:回滚事务的初步运用。 并且知道使用事务后, 事务中所有操作命令必须作为一个整体提交或回滚,如果事务中任何操作命令失败,则整个事务将因失败而回滚。   除了这个概念性的东西后,其他就不怎么知道了,比如事务的隔离性,具体怎么隔离、有几种隔离方式、执行顺序是什么。 我们今天来聊一聊这一块的内容(主要是事务的隔离性)。 回到顶部

chinaherolts2008的博客 1312

单细胞数据分析(三):单细胞聚类分析

本文介绍了单细胞聚类分析的基本概念及其在单细胞RNA测序(scRNA-seq)数据中的应用。单细胞聚类分析通过将具有相似基因表达模式的细胞分组到不同的簇中,帮助识别细胞类型、状态和功能。文章详细展示了使用R语言中的Seurat包进行单细胞数据聚类分析的步骤,包括数据加载、降维、聚类和结果可视化。通过FindNeighbors和FindClusters函数,文章展示了如何基于降维数据进行细胞聚类,并选择合适的分辨率值。

专注生信领域 1910

ASPICE标准快速掌握「2.1. 过程能力概览」

一个项目的质量流程是否做的好最终会需要由一个指标来确定,ASPICE将其称为过程能力(Process capability),过程能力是一个综合的判定概念。而为了实现这个概念,ASPICE建立了一套完整的过程评估模型(Process Assessment Model),通过这套评估模型最终就能得出过程能力的最终得分。项目组根据这个得分不断改进和优化得分不足的方面,从而约束整个流程的各个方面来间接提升项目的最终质量。这里有三个关键术语:其中最主要的就是PAM,即过程评估模型,由ASPICE给出,该模型可以看成

雪云飞星的博客 1184

锁和并发性----隔离级别

隔离级别决定事务间的可见程度,理解隔离级别是做什么的,你就能明白它们是如何阻止并发性副作用的。下面介绍各种事务隔离级别。Serializable Serializable隔离级别在SQL Server中是最悲观的隔离级别,它表明没有并发性问题。它简单地锁定一切,直到确保没有副作用发生,它通过范围锁实现这一点,这些锁要确保避免幻读的问题。范围锁如下图所示:...

weixin_34268169的博客 128

S7-200SMART通过表格指令实现模拟量信号滑动平均值滤波的具体方法

S7-200SMART通过表格指令实现模拟量信号滑动平均值滤波的具体方法

Robot_PLC_HMI_Automation 6727

搞懂 SQL Server 锁与阻塞,解决程序莫名卡死超时问题

SQL Server 的“卡死”通常不是性能问题,而是并发控制问题。搞懂锁,不是为了炫技,而是为了:不再背锅不再半夜被叫醒不再对着 Timeout 日志发呆希望你能淡定地说一句:“哦,又是锁。

2609_95039349的博客 207

32、机械臂数字孪生模型创建指南

本文介绍了如何在MATLAB Simscape中为一款3自由度(DOF)微型机械臂创建数字孪生模型。内容涵盖硬件参数测量、Simulink模型搭建流程,包括初始条件设置、基座与上部主体构建、上臂结构设计等关键步骤。通过使用Solid、Revolute Joint和Rigid Transform等模块,实现机械臂多体系统建模,并支持后续运动仿真与物理系统的对比诊断。读者可依据指南逐步完成模型构建,相关资源可通过MATLAB File Exchange或指定网站获取。

qsc9012345的博客 215

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SQLServer数据库原理读书笔记(一)--SQLServer体系结构

SQLServer体系结构:网络程序库,用户态调度器,关系引擎,OLE数据库,存储引擎,IO管理器,Win32API。 1.update 的执行分两种情况: 1)直接替换; 2)分成delete和insert两个操作分别执行; 2.SQLServer页面大小为8k,每8个页面组成一个“集”(extent),集是分配回收空间的最小单位; 3.事务通...

weixin_30709061的博客 95

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

擦亮自己的眼睛去看SQLServer之谈谈锁机制

今天,我们不谈抽象概念,而是深入 SQL Server 的锁内部,通过可运行的代码,看清锁的类型、兼容性、以及如何用动态管理视图(DMV)去“擦亮眼睛”观察它们。粒度越小,并发度越高,但锁管理开销越大。SQL Server 会根据查询计划、事务隔离级别和系统负载自动选择锁粒度,同时支持“锁升级”(Lock Escalation)——当单个事务持有超过 5000 个行锁时,会自动升级为表锁,以减少内存开销。例如,两个事务同时持有 S 锁可以共存,但一个事务持有 X 锁时,其他事务的 S 锁请求会阻塞。

mTvqbnoAU的博客 162

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

SQLserver中的事务以及数据并发的问题和事务的四种隔离级别

一个事务在读取某个范围的记录时,另一个事务插入或删除了一些记录,导致第一个事务再次读取时,似乎看到了“幻影”记录。在这个隔离级别下,事务在整个事务期间可以多次读取到相同的数据集合,即使其他事务修改了这些数据,也不能提交。:当一个事务读取到另一个未提交事务修改的数据时,如果那个事务最终回滚,那么第一个事务读取到的数据就是无效的。在这个级别下,事务会以一种顺序执行,就像它们是串行的一样,从而确保了最高的数据一致性,但会牺牲并发性能。在这个隔离级别下,事务可以读取到其他事务未提交的数据。

愿你历尽千帆,归来仍是少年。 4255

SQLServer事务隔离级别

数据库中的事物是具有原子性(Atomicity),一致性(Consistemcy),隔离性(Isolation),持久性(Durability)四个特征。 1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。 2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。 3、夺隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。 4、夺持久性(Dura

coco的专栏 5564

SQLServer事务、阻塞、死锁

阻塞和死锁是数据库应用的设计问题。从根本上来说,因为关系型数据库事务的原因,阻塞是必须的。阻塞和死锁产生的三大因素:连接持有锁的时间过长、锁的粒度较大、数目过多。锁产生的背景:事务。因为事务的ACID(原子性、一致性、隔离性、持久性)使得数据库在事务过程中,必须锁定要修改的资源。换句话说,阻塞是实现事务的隔离所带来的不可避免的代价。为了减少阻塞,可以从以下方面考虑:1、申请锁的互斥度。2、锁的范围...

lemon627497658的博客 6504

SQL server中的事务与锁

这种方法一旦超过时间,语句取消,释放资源,但是当前报错事务,不会回滚,会造成数据错误,你需要在程序中捕获1222错误,用程序处理当前事务的逻辑,使数据正确。锁的分类可以从锁的模式和锁的颗粒度分为两大类,锁的模式定义了事务对资源的访问方式,而锁的颗粒度分类决定了锁的作用域范围大小。允许事务读取其它事务未提交的数据,可能会造成脏读,隔离级别最低,可以提高并发性能。理解:允许事务读取另一个事务修改了但还未提交的数据,如果被读取的事务出现回滚时,该事务就读取到了数据库中没有真正存在过的数据,造成了脏读。

qq_61709335的博客 1140

sqlserver事务隔离级别

SQL Server事务隔离级别FILESTREAM-enabled databases support the following transaction isolation levels. (已启用 FILESTREAM 的数据库支持下列事务隔离级别)SET Transaction Isolation Level Read语法的四种情况第一种情况:第二种情况:第三种情况:第四种情况:语法基本语法示例一、ROWLOCK的使用二、SQL Server中使用ROWLOCK需要注意的地方 SET TRANSA

秋̶᭄ꦿ攻城狮࿆ྂ 822

SQLServer锁表

SQLServer锁表背景正文 背景 在数据库开发过程中,不得不考虑并发性的问题,因为很有可能当别人正在更新表中记录时,你又从该表中读数据,那你读出来的数据有可能就不是你希望得到的数据。可以说有些数据同时只能有一个事物去更新,否则最终显示给用户的数据不是数据库中现存的数据。锁表就限制不同的事物在同一时间内不允许同时操作一张表,实例很简单,可以用select来锁定整张表,那别人就不可能更新或是读取表...

分享技术,传播知识! 3745

Sql Server 锁、事务隔离级别

1.为什么需要锁(锁是为了解决什么问题) 丢失更新:在这种情况下,事务与事务之间没有隔离。多个事务能够读取同一份数据并且修改它。最后对数据集做出修改的事务将胜出,而其他所有事务所作的修改都丢失了。(Sql Server中对数据进行修改时需要排它锁锁住修改,其他任何事务对该数据的查询或修改均需要等待排它锁被释放,所以个人认为Sql Server并不会发生这种问题。) 脏读:在这种情况下,一个事务...

qq_42146247的博客 504

SQLServer事务管理和锁底层机制浅谈

title: SQLServer事务管理和锁 date: 2020-12-25 20:16:57 tags: T-SQL categories: db实验报告 实验十五 SQLServer2008 事务管理和锁 环境准备 创建数据库及表 create database student; use student; create table campus_card ( studcardid char(8), balance decimal(10,2) ); create table icbc_c.

qq_43413750的博客 571

mysql事务的隔 离级别_MSSQL事务、事务隔离级别、锁的简单总结

一、数据库事务1、事务是作为单个逻辑工作单元执行的一系列操作。可以是一条SQL语句也可以是多条SQL语句。2、事务具有四个特性原子性:不可分隔、成则具成、败则具败。恢滦裕菏挛裨谕瓿墒保 匦胧顾 械氖 荻急3忠恢伦刺?隔离性:独立的执行互不干扰。由并发事务所作的修改必须与任何其他并发事务所作的修改隔离(另外的描述:多个事务同时进行,它们之间应该互不干扰.应该防止一个事务处理其他事务也要修改的数据时,...

weixin_39626613的博客 192
上一篇: Hive进阶篇」详解存储格式及压缩方式
下一篇: SQL Server索引存储结构
thy822
博客等级 码龄19年 313粉丝 294原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值