一 概述
在数据库方面,对于非DBA的程序员来说,事务与锁是一大难点,针对该难点,本篇文章试图采用图文的方式来与大家一起探讨。
“浅谈SQL Server 事务与锁”这个专题共分两篇,上篇主讲事务及事务一致性问题,并简略的提及一下锁的种类和锁的控制级别。
下篇主讲SQL Server中的锁机制,锁控制级别和死锁的若干问题。
二 事务
1 何为事务
预览众多书籍,对于事务的定义,不同文献不同作者对其虽有细微差别却大致统一,我们将其抽象概括为:
事务:指封装且执行单个或多个操作的单个工作单元,在SqlServer中,其定义表现为显示定义和隐式定义两种方式。
基于如上的定义,我们可以将事务解剖拆分为如下几个点:
(1)事务是单个工作单元,这一定义,才使事务具有ACID属性
(2)事务是封装操作的,如封装基本的CRUD操作
--事务
Begin Tran
SELECT * FROM UserInfo
INSERT INTO UserInfo VALUES('Alan_beijing',35)
UPDATE UserInfo SET Age=31 WHERE UserName='Alan_beijing'
DELETE UserInfo WHERE UserName='Alan_beijing'
Commit Tran
(3)事务在封装操作时,可以封装单个操作,也可以封装多个操作(封装多个操作时,应注意与批处理的区别)
(4)在SqlServer中,事务的定义分为显示定义和隐式定义两种方式
显示定义:以Begin Tran作为开始,其中提交事务为Commit Tran,回滚事务为RollBack Tran,如我们在一个事务中插入两条操作语句
--显示定义事务
Begin Tran
INSERT INTO UserInfo VALUES('Alan_shanghai',30)
INSERT INTO UserInfo VALUES('Alan_beijing',35) Commit Tran
隐式定义:如果不显示定义事务,SQL Server 默认把每个语句当作一个事务来处理(执行完每个语句之后就自动提交事务)
2 事务的ACID属性
事务作为单个工作单元,该定义使其具有ACID属性,ACID属性指原子性(Atomicity)、一致性(Consisitency)、隔离性(Isolation)和持久性(Durability)。
(1)原子性(Atomicity)
原子性指事务必须是原子工作单元,即对于事务的封装操作,要么全部执行,要么全都不执行。如下情况均会导致事务的撤销或回滚。。。
a.事务提交之前,系统发生故障或重新启动,SQL Server将会撤销在事务中进行的所有操作;
b.事务处理中遇到错误,SQL Server通常会自动回滚事务,但也有少数例外;
c.一些不太严重的错误不会引发事务的自动回滚,如主键冲突,锁超时等;
d.可以使用错误处理代码来捕获一些错误,并采取相应的操作,如把错误记录在日志中,再回滚事务等;
(2)一致性(Consisitency)
一致性主要指数据一致性,即主要对象是数据。从宏观上来说,指某一段时间区间,数据要保持一致性状态,从微观上来说,某个时间点数据要保持一致性状态,我们举个例子,
假若有两个事务A和B对同一张表进行操作,A向表中写数据,B向数据表中读取数据,可以猜测,B读取的数据大致有三种粗粒度可能:
第一种可能:A还没向数据表中写入数据的状态;
第二种可能:A已向数据表中写入部分数据,但还未写完的状态;
第三种可能:A已向数据表中写完数据;
如此,造成了事务的不一致性。
关于事务一致性,可能会发生 丢失更新,脏读,不可重复读和幻读等问题,下文会详细论述这些事务一致性问题。
(3)隔离性(Isolation)
隔离性指当两个及其以上事务对同一边界资源进行操作时,要控制好每个事务的边界,控制好数据访问机制,确保事务只能访问处于期望的一致性级别下的数据。
在SQL Server中,一般采用锁机制来控制,下文中,我们会详细论述。
(4)持久性(Durability)
我们对数据表进行操作时,一般会按照先后顺序执行如下两步:
第一步:将对数据表操作写入到磁盘上数据库的事务日志中(持久还到磁盘事务日志中);
第二步:完成第一步后,再将对数据表操作写入到磁盘上数据库的数据分区中(持久化到磁盘上数据库分区中);
关于如上两步,我们来想想可能发生的问题:
问题1:完成如上第一步之前,系统发生故障(如系统异常,系统重启),数据库引擎会怎么做?
由于未完成第一步,提交指令还未记录到磁盘的事务日志中,此时事务并未持久化,系统发生故障后,SQL Server
会检查每个数据库的事务日志,进行恢复处理(恢复处理一般 |