《数据库原理》实验报告 题目:实验七 学号 2013302478 姓名 纪昌宇 班级 10011301 日期 2015.11.14 事务与并发控制 1. 实验七:事务与并发控制
1.1. 实验目的
1. 掌握事务机制,学会创建事务。
2. 理解事务并发操作所可能导致的数据不一致性问题,用实验展现四种数据不一致性
问题:丢失修改、读脏数据、不可重复读以及幻读现象。
3. 理解锁机制,学会采用锁与事务隔离级别解决数据不一致的问题。 4. 了解数据库的事务日志。
1.2. 实验内容
假设学校允许学生将银行卡和校园卡进行绑定,在student数据库中有如下的基本表,其中校园卡编号cardid即为学生的学号:
icbc_card(studcardid,icbcid,balance) //校园卡ID,工行卡ID,银行卡余额
campus_card(studcardid,balance) //校园卡ID,校园卡余额
数据创建的代码: usestudent
createtablecampus_card ( studcardidChar(8), balanceDecimal(10,2))
createtableicbc_card (
studcardidChar(8), icbcidChar(10),
balanceDecimal(10,2)
)
insertintocampus_cardvalues('20150031', 30) insertintocampus_cardvalues('20150032', 50) insertintocampus_cardvalues('20150033', 70)
insertintoicbc_cardvalues('20150031','2015003101', 1000) insertintoicbc_cardvalues('20150032','2015003201', 1000) insertintoicbc_cardvalues('20150033','2015003301', 1000)
针对以上数据库按照要求完成下列实验:
1. 编写一个事务处理(begin tran)实现如下的操作:某学号为20150032的学生要从银
行卡中转账200元到校园卡中,若中间出现故障则进行rollback。(15分)
settransactionisolationlevel repeatableread
begintransaction usestudent go
declare@xdecimal(10, 2) select@x=balance fromicbc_card
wherestudcardid='20150032' set@x=@x-200 if(@x>=0) begin
updateicbc_cardsetbalance=@xwherestudcardid='20150032'
updatecampus_cardsetbalance=balance+200 wherestudcardid='20150032' committran end else begin
print'余额不足,不能转账' rollbacktran end
2. 针对本题的数据库和表,分别用具体的例子展现四种数据不一致问题:丢失修改、
读脏数据、不可重复读和幻读(删除和插入)。(40分,每种数据不一致10分) (1).丢失修改 --事务1
begintran
declare@balancedecimal(10,2)
select@balance=balancefromcampus_cardwherestudcardid='20150033' waitfordelay'00:00:05' set@balance=@balance-10
updatecampus_cardsetbalance=@balancewherestudcardid='20150033' committran go
selectbalancefromcampus_cardwherestudcardid='20150033'
--事务2
begintran
declare@balance1decimal(10,2)
select@balance1=balancefromcampus_cardwherestudcardid='20150033' waitfordelay'00:00:05' set@balance1=@balance1-20
updatecampus_cardsetbalance=@balance1wherestudcardid='20150033' committran go
selectbalancefromcampus_cardwherestudca
【事务1】更改了数据,结果为60,但是没有被读到。最终【事务2】的结果50覆盖了【事
务1】的更改值,结果不是期望值40
(2).读脏数据
--事务1
SETTRANSACTIONISOLATIONLEVELREADUNCOMMITTED
--READ UNCOMMITTED 执行脏读,不发出共享锁,也不接受排他锁 begintran
declare@balancedecimal(10,2)
select@balance=balancefromcampus_cardwherestudcardid='20150032' updatecampus_cardsetbalance=@balance+100 wherestudcardid='20150032' waitfordelay'00:00:05' rollbacktran--回滚 go
selectbalancefromcampus_cardwherestudcardid='20150032'
--事务2
SETTRANSACTIONISOLATIONLEVELREADUNCOMMITTED begintran
declare@balancedecimal(10,2)
select@balance=balancefromcampus_cardwherestudcardid='20150032' updatecampus_cardsetbalance=@balance+50 wherestudcardid='20150032' committran go
selectbalancefromcampus_cardwherestudcardid='20150032'
【事务1】更改了数据,【事务2】读取了表中更改后的值再进行操作,【事务1】回滚。最终的表存储了错误结果。
(3)不可重复读 --事务1
SETTRANSACTIONISOLATIONLEVELREADCOMMITTED begintran
--事务2
SETTRANSACTIONISOLATIONLEVELREADCOMMITTED begintran
updatecampus_cardsetbalance=balance+200 wherestudcardid='20150031' committran
selectbalancefromcampus_cardwherestudcardid='20150031' waitfordelay'00:00:05'
selectbalancefromcampus_cardwherestudcardid='20150031' committran