读书笔记 SQL 事务理解

事务的ACID属性

Atomicity 原子性

每个事务作为原子单元工作(即不可以再拆分),也就是说所有数据库变动事务,要么成功要么不成功。

SQL Server把每个DML或者 DDL命令都当做一个事务。不允许任何命令只是部分成功。 比如一个UPDATE语句更新500行,除非500行全部更新,否则有任何情况阻止该命令更新。SQL Server会终止该命令更新,并且回滚事务。

Consistency 一致性

每个事务,不论成功或失败,数据库中定义的约束状态必须一致,否则会回滚。

比方说一个事务企图插入一个无效的外键,这会被SQL Server见到到违反约束,并且生成一个错误提示。

Isolation 隔离性

事务的执行看上去是互不干扰的,隔离的程度基于隔离级别设置。比方说,两个事务要更改同一个数据,其中之一必须等另外一个完成以后才能去修改。

SQL Server用‘锁’来达到事务的隔离的目的。 通常有两种锁 Shared locks 共享锁 用作读取数据  Exclusive locks 排它锁 用作变更数据

Durability 持久性

事务操作结果都会被保存下来(事务日志 database transaction log)。每个数据库变动(数据修改语句或者DDL语句)首先会把原始版本的数据(updates和deletes)写到事务日志,当事务提交,并且所有一致性检查都通过以后,事件成功提交的事实就会写入事务日志。如果数据库此之前意外当机,那么再次启动后,数据会回滚。

阻塞 Blocking

如果两个seesion在同样的资源上申请排它锁 ,当其中一个生成排它锁以后,另外一个必须等第一个释放后(commmit 或者 roll back)才能申请。也就是说同一时间内,两个会话无法写入同一个资源, 这样,一个写入阻塞了另外一个写入。这就叫阻塞

除了同一资源申请排它锁会造成堵塞之外,一个排他锁也会阻止其他事务读取同样的资源。因为排它锁和共享锁是不相容的。

死锁 Deadlocking

如果有两个或多个Session互相阻塞,这就会造成死锁。当SQL Server 检测到以后,会中断其中一个,然后返回错误信息 1205.

Session 1 Session 2

USE TSQL2012;
BEGIN TRAN;


USE TSQL2012;
BEGIN TRAN;


UPDATE HR.Employees
SET Region = N‘10004‘
WHERE empid = 1

 
 
UPDATE Production.Suppliers
SET Fax = N‘555-1212‘
WHERE supplierid = 1


UPDATE Production.Suppliers
SET Fax = N‘555-1212‘
WHERE supplierid = 1

 
<blocked>
UPDATE HR.Employees
SET phone = N‘555-9999‘
WHERE empid = 1

  <blocked>

发生死锁以后其中一个事务会完成,而另外一个会被中断,并且显示1205错误信息

Msg 1205, Level 13, State 51, Line 1
Transaction (Process ID 61) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

最后可以把成功执行事务回滚

IF @@TRANCOUNT > 0 ROLLBACK IF @@TRANCOUNT > 0 ROLLBACK

@@TRANCOUNT

用来返回在当前连接上执行的 BEGIN TRANSACTION 语句的数目。

如果返回0则表示当前不在一个事务里面, 1表示在一个事务里面,大于1则表示在一个嵌套的事务里面。

注意一个事务只能包含一个ROLLBACK 命令,他会回滚整个事务,然后重置 @@TRANCOUNT 为0

实际例子如下

1. COMMIT TRAN

USE TSQL2012;
SELECT @@TRANCOUNT; -- = 0
BEGIN TRAN;
    SELECT @@TRANCOUNT; -- = 1
    BEGIN TRAN;
        SELECT @@TRANCOUNT; -- = 2
        -- Issue data modification or DDL commands here
    COMMIT
    SELECT @@TRANCOUNT; -- = 1
COMMIT TRAN;
SELECT @@TRANCOUNT; -- = 0

2. ROLLBACK TRAN

USE TSQL2012;
SELECT @@TRANCOUNT; -- = 0
BEGIN TRAN;
    SELECT @@TRANCOUNT; -- = 1
    BEGIN TRAN;
        SELECT @@TRANCOUNT; -- = 2
        -- Issue data modification or DDL command here
    ROLLBACK; -- rolls back the entire transaction at this point
SELECT @@TRANCOUNT; -- = 0

事务隔离级别

READ COMMITTED 

这个是默认隔离级别,只有数据更改被提交以后才能被读取们所有SELECT语句会企图取得一个共享锁,修改数据的另外一个事务会话的排他锁会阻塞READ COMMITTED 会话。

在查询语句加入 WITH (NOLOCK) 或 WITH (READUNCOMMITTED)可以直接读取

注意现在 WITH (NOLOCK) 不推荐使用,在新的SQL 版本中 Update和Delete 语句里面不允许用这个选项了。去而代之的是 WITH (READUNCOMMITTED)

SELECT lastname, firstname
FROM HR.Employees WITH (READUNCOMMITTED);

例子: 写入阻塞写入

Session 1 Session 2

USE TSQL2012;
BEGIN TRAN;

USE TSQL2012;

UPDATE HR.Employees

SET postalcode = N‘10004‘

WHERE empid = 1;


UPDATE HR.Employees

SET phone = N‘555-9999‘

WHERE empid = 1;

<more work> <blocked>
COMMIT TRAN;  
  <results returned>

写入阻塞读取

Session 1 Session 2

USE TSQL2012;

BEGIN TRAN;

USE TSQL2012;

UPDATE HR.Employees

SET postalcode = N‘10005‘

WHERE empid = 1


SELECT lastname, firstname

FROM HR.Employees

 
<blocked>

COMMIT TRAN;  
  <results returned>

READ UNCOMMMITED

这个隔离级别允许reader读取未提交的数据,这个设定使得SELECT 语句不用申请共享锁,不会被writer阻塞。然而被读取的数据在随后可能会回滚到原来的状态,这回导致脏读(reading dirty data)

例子

Session 1 Session 2

USE TSQL2012;

BEGIN TRAN;


USE TSQL2012;

SET TRANSACTION ISOLATION LEVEL READ

UNCOMMITTED;


UPDATE HR.Employees

SET region = N‘1004‘

WHERE empid = 1;

 
 
SELECT lastname, firstname, region

FROM HR.Employees

  <results returned: region = 1004 for empid = 1>
ROLLBACK TRAN;  

<region for empid = 1 rolled back to

original value>


SELECT lastname, firstname, region

FROM HR.Employees;

  <results returned: region = original value for empid = 1>

READ COMMITTED SNAPSHOT 这个实际上不是一个新的隔离级别,这是 READ COMMITTED的一个选项,该隔离级别有以下特性:

●使用tempdb来存储被修改数据的原始版本。 这样当reader 读取数据的时候读取的是原始版本 ,不需要共享锁,也不会被writer阻塞。  即读取 (原始)提交数据。

●READ COMMITTED SNAPSHOT 选项可以针对每个数据库设置

●RCSI(READ COMMITTED SNAPSHOT ) 不是独立的隔离级别,与READ COMMITTED的区别仅仅是防止writer阻塞reader。

●RCSI 是Windows Azure SQL Database的默认隔离级别

REPEATABLE READ   在事务结束之前,该事务中的每个读取操作都是可重复的。所有被读取的数据都会被共享锁锁定,读取过程中其他更新或删除的事务无法对这些数据做更改。 不过事务读取完成以后,可能会有新的数据行加入进来,导致幻读(phantom read)

SNAPSHOT 该隔离级别同样使用tempdb来空置行的版本控制,事务只能识别在其开始之前提交的数据修改。 在当前事务中执行的语句将看不到在当前事务开始以后由其他事务所做的数据修改。所以不存在幻读(phantom read) ,事务中的语句所获取的已提交数据快照对应于该数据在事务开始时的状态。SNAPSHOT 隔离级别不需要共享锁

SERIALIZABLE  最强的隔离。在一个SELECT事务完成之前,其他事务无法向表中插入新行。

事务模式 Transaction Modes

Autocommit

单个数据修改或者DDL 被执行以后,如果执行成功会自动提交。

Implicit transaction

隐式声明,先要开启隐式声明,然后每个语句执行以后不会自动提交或者回滚,需要手动处理。例子如下:

USE TSQL2012;
SET IMPLICIT_TRANSACTIONS ON;
SELECT @@TRANCOUNT; -- 0
SET IDENTITY_INSERT Production.Products ON;
-- Issue DML or DDL command here
INSERT INTO Production.Products(productid, productname, supplierid, categoryid,     unitprice, discontinued)
    VALUES(101, N‘Test2: Bad categoryid‘, 1, 1, 18.00, 0);
SELECT @@TRANCOUNT; -- 1
COMMIT TRAN;
SET IDENTITY_INSERT Production.Products OFF;
SET IMPLICIT_TRANSACTIONS OFF;
-- Remove the inserted row
DELETE FROM Production.Products WHERE productid = 101; -- Note the row is deleted

Explicit transaction mode

显式声明,就是用BEGIN TRANSACTION 或者 BEGIN TRAN 命令开始一个事务。例子如下:

USE TSQL2012;
SELECT @@TRANCOUNT; -- 0
BEGIN TRAN;
    SELECT @@TRANCOUNT; -- 1
    SET IDENTITY_INSERT Production.Products ON;
    INSERT INTO Production.Products(productid, productname, supplierid, categoryid,     unitprice, discontinued)
        VALUES(101, N‘Test2: Bad categoryid‘, 1, 1, 18.00, 0);
    SELECT @@TRANCOUNT; -- 1
    SET IDENTITY_INSERT Production.Products OFF;
COMMIT TRAN;

参考文档

sys.dm_tran_database_transactions

https://msdn.microsoft.com/en-us/library/ms186957(v=sql.90).aspx

Write-Ahead Transaction Log

http://msdn.microsoft.com/en-us/library/ms186259(SQL.105).aspx

@@TRANCOUNT

https://msdn.microsoft.com/zh-cn/library/ms187967.aspx

Detecting and Ending Deadlocks

https://msdn.microsoft.com/en-us/library/ms178104(SQL.105).aspx

事务隔离级别

https://msdn.microsoft.com/zh-cn/library/dn133175.aspx

时间: 2024-11-10 13:06:15

读书笔记 SQL 事务理解的相关文章

《SQL Server企业级平台管理实践》读书笔记——SQL Server数据库文件分配方式

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server数据库文件分配方式 1.文件分配方式以及文件空间检查方法 最常用的检查数据文件和表大小的命令就是:sp_spaceused 此命令有三个缺陷:1.无法直观的看出每个数据文件和日志文件的使用情况.2.这个存储过程依赖SQL Server存储在一些系统视图里的空间使用统计信息计算出的结果,如果没有更新空间统计信息,比如刚刚发生大数据插入,sp_spaceused的结果就不准确.3.这个命令主要是针对普通用户的数据库,对

第七章读书笔记《深入理解计算机系统》

第七章 读书笔记<深入理解计算机系统> 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或拷贝)到存储器并执行. 链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于加载时,也就是在程序被加载器加载到存储器并执行时:甚至执行于运行时,由应用程序来执行. 在早期的计算机系统中,链接是手动执行的.在现代系统中,链接是由叫链接器的自动执行的. 7.1 编译器驱动程序 1.大部分编译系统提供编译驱动程序:代表用户在需要时调用语言预处理器.编译器.汇编器

《SQL Server企业级平台管理实践》读书笔记——SQL Server如何设置自动增长和自动收缩项

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server如何设置自动增长和自动收缩项 SQL Server允许用户设置数据库初始值和最大值,可以通过自动增长或者自动收缩进行配置.通过这些配置,我们可以防止数据库空间问题而导致的应用程序修改失败或者SQL Server磁盘空间耗尽的事情发生.一般来讲,如果数据库不是很忙,默认的设置为自动增长,这种方式能够满足大部分的需求.但是在大量并发的情况下,申请数据文件和日志文件增长本身是一件非常消耗系统资源和影响性能的工作.所以如果

《SQL Server企业级平台管理实践》读书笔记——SQL Server中收缩数据库不好用的原因

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server中收缩数据库不好用的原因 数据库管理员有时候需要控制文件的大小,可能选择收缩文件,或者把某些数据文件情况以便从数据库里删除. 这时候我们就要使用到DBCC SHRINKFILE命令,此命令的脚本为: DBCC SHRINKFILE ( { file_name | file_id } { [ , EMPTYFILE ] | [ [ , target_size ] [ , { NOTRUNCATE | TRUNCATE

读书笔记:事务信息系统(上)

花好了很多时间读了事务信息系统:并发控制与恢复的理论.算法与实践 英文名叫 Transactional Information Systems: Theory, Algorithms, and the Practice of Concurrency Control 这本书在国内的翻译版已经绝版了,似乎没出过影印版.为了尝试看完,用pdf打印了出来,足有880页,装订了两册~~~好沉的 之所以读这本书的原因在于读着读着Jim Gray那本经典事务书,发现有这本,由于Jim Gray那本太沉,不好拿

1. SQL读书笔记——SQL中的连接(1)

<SQL学习指南>中的第5章 1.连接: 在某种机制下,需要将多个表中的数据进行整合到一起,即同一个查询的结果集中包含来自两个或者两个以上的表,这种机制被称为连接(join). 1.1 ANSI连接语法 本文采用的都是符合SQL92版本的ANSI SQL标准,所有的主流数据库都采用了SQL92的连接语法.由于这些数据库都出现SQL92标准发布之前,同时存在一些旧的连接语法,如下所示: 例子1: SELECT e.fname, e.lname, d.`name` FROM employee e

《SQL Server企业级平台管理实践》读书笔记——SQL Server中关于系统库Tempdb总结

Tempdb系统数据库是一个全局资源.可供连接到SQL Server实例的全部用户使用. 存储的内容项: 1.用户对象 用户对象由用户显示创建.这些对象能够位于用户会话的作用域中.也能够位于创建对象所用例程的作用域中. 例程能够是存储过程.触发器或用户自己定义函数. 用户对象能够是一下项内容之中的一个: 用户定义的表和索引 系统表和索引 全局暂时表和索引 table变量 表值函数中返回的表 2.内部对象 内部对象是依据须要由SQL Server数据库引擎创建的,用户处理SQL Server语句.

《SQL Server企业级平台管理实践》读书笔记——SQL Server中数据文件空间使用与管理

1.表和索引存储结构 在SQL Server2005以前,一个表格是以一个B树或者一个堆(heap)存放的.每个B树或者堆,在sysindexes里面都有一条记录相对应.SQL Server2005以后,引入了分区表的概念(Table Partition),在存储组织上,现有的分区基本上替代了原来表格的概念,原先表的概念成为了一个逻辑概念.一个分区就是一个B树或者一个堆.而一张表格则是一个到多个分区的组合. 1.1用B树存储于聚集索引的表数据页 如果一个表格上有聚集索引(Clustered In

读书笔记《深入理解计算机系统》(第三版) 概述

<深入理解计算机系统>第三版刚出来不到一周,便买下了这本书:之所以阅读本书,一方面源于网友推荐以及豆瓣不错的评分.评价:另一方面是针对本人非科班出身,计算机系统相关的知识相对比较薄弱,很多情况下此类知识需要工作之外的时间自学.补涨此类知识,而该书从程序员的角度进行阐述.展示了计算机系统的各个层面的知识以及其影响程序的正确性.性能.实用性,更容易引起某些上层和下层的知识接轨理解,以期望可以融汇各方面的知识. 明白程序的运作过程,编写更好的软件程序,对底层过程了解以完善自己知识体系和提高信心.接下