SQL Server数据库高级进阶之事务实战演练

1、SQL Server事务的本质

•  什么是SQL Server数据库事务?
事务:
是做为单个工做单元而执行的--系列操做,如查询和修改数据,甚至多是修改数据定义。
事务:保持逻辑数据一致性与可恢复性,必不可少的利器。

•  SQL Server数据库事务举例
在一个事务中,你写了2条sql语句,一条是修改订单表状态,一条是修改库存表库存-1 。 若是在修改订单表状态的时候出错,事务可以回滚,数据将恢复到没修改以前的数据状态,下面的修改库存也就不执行,这样确保你关系逻辑的一致,安全。html

• 阿笨对SQL Server事务一句话总结
即这一组命令要么都执行,要么都不执行,通俗的理解就是共同进退。sql

2、SQL Server事务分类

SQL Server定义事务边界的方式分为显式事务隐式事务两种。

•  显式事务:明确指出事务的起止边界。若是不显式定义事务的边界,SQL Server 会默认把每一个单独的语句做为-一个事务;换句话说,SQLServer默认在执行完每一个语句以后就自动提交事务。

显示事务须要定义以BEGIN TRAN语句做为开始。若是想提交事务,则应该以COMMIT TRAN语句显式结束事务;若是不想提交事务(撤消事务中的修改),则应该以ROLLBACK TRAN语句显式结束事务。

•  隐式事务:SQL查询分析器中,当前会话默认就是为隐式事务。每执行一条DML操做,就直接提交到数据库保存。数据库

3、SQL Server事务的小陷阱

下面的例子将两个INSERT语句封装在由BEGIN TRAN和COMMIT TRAN定义的一个显示事务边界中:安全

BEGIN TRAN;性能优化

INSERT INTO dbo. T1(keyco], col1, co12) VALUES(4, 101,'C);服务器

INSERT INTO dbo. T1(keyco], col1, co12) VALUES(4, 101,'C);微信

COMMIT TRAN;并发

T-SQL使用下列语句来管理完整的事务(事务的基本三要素):app

•  开始事务:BEGIN TRANSACTIONide

•  提交事务:COMMIT TRANSACTION

•  回滚(撤销)事务:ROLLBACK TRANSACTION

•  存储点语句:SAVE TRANSACTION(可选)

所谓事务存储点就是在事务过程中插入若干个标记,当事务执行中出现错误时,能够不撤销整个事务,只是撤销部分事务,将事务退回到某个事物存储点。一旦事务提交或回滚,则事务结束。(备注:将事务回滚在初始状态成本有点大,那么关于事务使用存储点根据实际业务状况来断定是否使用。)

•   阿笨我的总结:
默认的隐式事务,在SQL Server查询分析器中每个单独的语句就是一个事务,若是多行语句块须要包裹在一个事务中的话,则须要手动的开启显示事务。

(2条消息)SQL Server中的事务(附有实例)_数据库_legendaryhaha的博客-CSDN博客 https://blog.csdn.net/legendaryhaha/article/details/80550180?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

4、SQL Server事务的特性

事务必须有四个属性:原子性(Atomicity)、一致性 (Consistency)、隔离性(Isolation)、持久性(Durability) ,这4个属性的首字母能够缩写为ACID。

1240

A帐号向B帐号转帐200

•  原子性(Atomicity)

原子性是指事务是一个不可分割的工做单位,事务中的操做要么都发生,要么都不发生。

针对同一个事务

操做前A:800,B:200

操做后A:600,B:400

一致性表示事务完成后,符合逻辑运算。

•  一致性(Consistency)

事务先后数据的完整性必须保持一致。

针对一个事务操做前与操做后的状态一致

操做前A:800,B:200

操做后A:600,B:400

一致性表示事务完成后,符合逻辑运算

•  隔离性(Isolation)

事务的隔离性是多个用户并发访问数据库时,数据库为每个用户开启的事务,不能被其余事务的操做数据所干扰,多个并发事务之间要相互隔离。

针对多个用户同时操做(两个事务同时进行),主要是排除其余事务对本次事务的影响。

即不一样事务之间的相互影响和隔离的程度。好比,不一样的隔离级别,事务的并发程度也不一样,最强的隔离状态是全部的事务都是串行化的(serializable)(即一个事务完成以后才能进行下一个事务),这样并发性也会降到最低,在保证了强一致性的状况下,性能也会受很大影响,因此在实际工程当中,每每会折中一下。每一个RMDB关系型数据库的事务默认隔离级别是不同的。

•  持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即便数据库发生故障也不该该对其有任何影响。

SQL SERVER经过write-ahead transaction log来保证持久性。write-ahead transaction log的意思是,事务中对数据库的改变在写入到数据库以前,首先写入到事务日志中。而事务日志是按照顺序排号的(LSN)。当数据库崩溃或者服务器断点时,重启动SQL SERVER,SQL SERVER首先会检查日志顺序号,将本应对数据库作更改而未作的部分持久化到数据库,从而保证了持久性.。

表示事务结束后的数据不随着外界缘由致使数据丢失

操做前A:800,B:200

操做后A:600,B:400

若是在操做前(事务尚未提交)服务器宕机或者断电,那么重启数据库之后,数据状态应该为

A:800,B:200

若是在操做后(事务已经提交)服务器宕机或者断电,那么重启数据库之后,数据状态应该为

A:600,B:400

5、SQL Server事务的隔离级别

1)、什么是数据库隔离级别

数据库的隔离级别其实是针对事务的隔离级别来讲的,它是用来限制一个事务中正在读取或被修改的数据免于被其余事务修改的程度。理论上每一个事务和其余的事务都应该彻底隔离开来。然而出于性能和可行性的缘由,实践中几乎不可能作到的。

2)、数据库为何要有事务的隔离级别

在并发环境下若是没有锁和隔离级别, 不考虑事务的隔离性可能引起的问题 可能会发生如下四种状况:

脏读:在这种状况下,一个事务可以读取另外一个事务正在修改且未提交的数据,那么另外一个事务若是发生回滚操做,将致使第一个事务读取到的数据和实际的数据不一致;

丢失更新:这种状况下,事务没有隔离。多个事务可以读取同一份数据而且修改它。最后对数据集作出修改的事务将胜出,而其余的事务所作的修改都失效;

不可重复读:两个事务读取数据,可是在第二个事务读取前,另外一个事务修改了该数据,所以两次读取的数据不一致;

幻读:这种状况和不可重复读相似,不一样的是,两个事务读取一个范围的数据,可是在第二个事务读取以前,另外一个事务新增了一条数据,致使两次读取的结果不一样。

要想解决脏读、不可重复读、幻读等读现象,那么就须要提升事务的隔离级别。但与此同时,事务的隔离级别越高,并发能力也就越低。因此,还须要读者根据业务须要进行权衡。 

在了解了并发状况下出现的上述问题后,就能够进一步理解隔离级别的概念,通俗一点讲就是:你但愿以何种方式将并发的事务隔离开来, 隔离到什么程度?好比容许脏读,等。隔离级别越高,读取脏数据或者形成数据不一致的状况就越少,可是在高并发系统中的性能下降就越严重。

2)、Sql Server支持6种隔离级别

•  未提交读(Read Uncommited)

•  已提交读(Read Commited)(Sql Server的默认事务隔离级)

•  可重复读(Repeatable Read)

•  序列化(Serializable)

•  快照(Snapshot)

•  已提交读快照(Read Commited Snapshot)

查看SQL Server当前会话的隔离级别 

DBCC USEROPTIONS  

Sql Server的默认事务隔离级别是已提交读(Read Commited),一个事务不容许读取另外一个事务未提交的数据。

Mysql默认的事务处理级别是可重复读(Repeatable Read)也就是可重复读。

Oracle默认系统事务隔离级别是已提交读(Read Commited),也就是读已提交。

备注:实际工做中通常数据库默认的事务隔离级别作好不要去作修改。

6、SQL Server事务的实战运用场景

1)、批量一次性提交事务处理数据(插入)。

一)、为何一次性提交事务批量插入数据效率最高?

使用事务能够提升数据的插入效率,这是由于进行一个INSERT操做时,SQL SERVER内部会创建一个事务,在事务内才进行真正插入处理操做。经过使用事务能够减小建立事务的消耗,全部插入都在执行后才进行提交操做。

二)、关于批量插入大数据的带来的思考总结

•  为了提高效率,数据能一次提交不作屡次提交;

•  能一次插入解析sql不要屡次提交解析sql;

•  插入数据量太大时,须要程序预先切割数据;

2)、在事务范围中如何防止查询大面积的数据行内出现死锁的状况

要提高SQL的查询效能,通常来讲你们会以创建索引(index)为第一考虑。其实除了index的创建以外,当咱们在下SQL Command时,在语法中加一段WITH (NOLOCK)能够改善在线大量查询的环境中数据集被LOCK的现象藉此改善查询的效能。

锁争用的解决方法:SQL Server开始是用行级锁的,可是常常会扩大为页面锁和表锁,最终形成死锁。 幸运的是,咱们能够经过SQL Server 的NOLOCK来手工处理。

NOLOCK的使用
NOLOCK能够忽略锁,直接从数据库读取数据。这意味着能够避开锁,从而提升性能和扩展性。不过有一点千万要注意的就是,WITH (NOLOCK)的SQL SELECT有可能会形成Dirty Read,就是读到无效的数据。

SQLServer性能优化之 nolock,大幅提高数据库查询性能 - 雲霏霏
 http://www.javashuo.com/article/p-koljamfa-t.html

7、SQL Server事务遵照原则

编写事务时要遵照的原则大概总结以下:

•  事务尽量简短:

  事务启动至结束后再数据库管理系统中保留大量资源,以保证事务的原子性、一致性,隔离性和持久性。若是在多用户系统中,较大的事务将会占用系统的大量资源,是系统不堪重负,会影响软件的性能,甚至致使系统崩溃。

•  事务中访问的数据量尽可能最少:

  当并发执行事务处理时,事务操做的数据量越少,事务之间对操做数据的争夺就越少。

•  查询数据时尽可能不要使用事务:

  对数据进行浏览查询操做并不会更新数据库的数据,所以尽可能不使用事务查询数据,避免占用过量的系统资源。

•  在事务处理过程当中尽可能不要出现等待用户输入的操做:

   在处理事务的过程当中,若是须要等待用户输入数据,那么事务会长时间地占用资源,有可能形成系统阻塞。

【网易云课堂】:点击在线观看

【腾讯课堂】:点击在线观看

【微信公众号】:跟着阿笨一块儿玩NET

相关文章
相关标签/搜索