yzx99

导航

 

用了半辈子存贮过程,却没有严格意义地使用事务,今天看到自己以前写的一个SQL事务测试的存贮过程,心血来潮,开始整理一下:
从简单的说起,如果insert、update、delete放在begin tran与commit tran/rollback tran之间,则操作不会被立即执行,而是等到commit tran时才执行,如果遇到rollback tran则取消。这里使用insert来测试,数据库使用pubs的,示例代码:

S_Test1 

 

这个应该没有问题,现在的多一些问题,在没有提交或回滚前,SQL是否能检测到记录成功插入,示例代码:

S_Test2


结果表明,在回滚之前,SQL语句是检测得到记录插入的。

再来,如果在回滚之前,另一个进程的SQL语句能否检测得到记录的插入,代码如下:

S_Test3

查询分析器中开两个窗口,一个窗口执行S_Test3,另一个窗口执行
  select count(*) from jobs where job_desc='yzx-test2'
结果我“惊奇地”发现,第二个窗口要等到第一个窗口执行完毕后才能再执行。加大延迟时间,再去查看当前活动的“锁/进程ID”,
spid 53 (正在阻塞),对应命令:S_Test3,
对象 锁类型 模式 状态 所有者 索引 资源
pubs DB S GRANT Sess
pubs.dbo.jobs KEY X GRANT Xact PK__jobs__117F9D94 (1500140b9389)
pubs.dbo.jobs PAG IX GRANT Xact PK__jobs__117F9D94 1:115
pubs.dbo.jobs TAB IX GRANT Xact

spid 54 (阻塞者53),对应命令:select count(*) from jobs where job_desc='yzx-test2'
对象 锁类型 模式 状态 所有者 索引 资源
pubs DB S GRANT Sess
pubs.dbo.jobs KEY S WAIT Xact PK__jobs__117F9D94 (1500140b9389)
pubs.dbo.jobs PAG IS GRANT Xact PK__jobs__117F9D94 1:115
pubs.dbo.jobs TAB IS GRANT Xact
可以看出spid 53中在锁类型为KEY的位置有一个排它锁X,导致spid 54访问相同KEY位置时处于等待。(锁类型与模式的详细说明可查SQL帮助文档中的“访问和更改关系数据”->“锁定”->“显示锁定信息”与“SQL Server 中的锁定介绍”

这个结果意味着,对于事务,不要太随意使用了,否则造成其它进程的延时,与我的实际经验符合,即事务只用在要处理的那几句就好。

现在再试一种情况:事务中,如果直接退出,到底是提交还是回滚?

S_Test4

系统执行后出错,错误信息:
EXECUTE 后的事务计数指出缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。原计数 = 1,当前计数 = 2。
结果是数据写进去了。即默认是提交。

记得以前我与朋友曾经讨论过事务是否保证原子性,该问题的应用范围是生成最大单号,示例代码如下:

S_Test5

在查询分析器的两个窗口中同时运行该存贮过程(一先一后,没差几秒),只有当前一个执行完毕后,后一个现在看来,因为有锁的存在,所以使用事务就可以保证单号的唯一性。

最后再试一个,如果事务中出错会如何?

S_Test6

测试结果,应该是系统继续向前走,所以后面是提交就提交,后面是回滚就回滚。

我能知道的事务就这些了,但关于锁、出错处理,还是要抽空去测试一下它的特性。

 

posted on 2009-02-25 17:19  yzx99  阅读(475)  评论(0编辑  收藏  举报