西工大数据库实验报告7Word文档格式.docx
- 文档编号:22560274
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:21
- 大小:692.84KB
西工大数据库实验报告7Word文档格式.docx
《西工大数据库实验报告7Word文档格式.docx》由会员分享,可在线阅读,更多相关《西工大数据库实验报告7Word文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
假设学校允许学生将银行卡和校园卡进行绑定,在student数据库中有如下的基本表,其中校园卡编号cardid即为学生的学号:
icbc_card(studcardid,icbcid,balance)//校园卡ID,工行卡ID,银行卡余额
campus_card(studcardid,balance)//校园卡ID,校园卡余额
创建数据库的代码如下:
createtablecampus_card
(studcardidChar(8),
balanceDecimal(10,2))
createtableicbc_card
(
studcardidChar(8),
icbcidChar(10),
balanceDecimal(10,2)
)
执行结果如图:
向该数据库插入数据的代码如下,执行结果如下图:
insertintocampus_cardvalues('
20150031'
30)
20150032'
50)
20150033'
70)
insertintoicbc_cardvalues('
'
2015003101'
1000)
2015003201'
2015003301'
可以看出,执行插入数据的语句后,数据库相关的表里成功出现插入的数据:
针对以上数据库按照要求完成下列实验:
1.编写一个事务处理(begintran)实现如下的操作:
某学号为********的学生要从银行卡中转账200元到校园卡中,若中间出现故障则进行rollback。
(15分)
创建该事务的代码如下,执行结果如图:
begintransaction
declare@xdecimal(10,2)
select@x=balance
fromicbc_card
wherestudcardid='
set@x=@x-200
if(@x>
0)
begin
updateicbc_card
setbalance=@x
updatecampus_card
setbalance=balance+200
committransaction
end
else
print'
余额不足,交易失败'
rollbacktransaction
然后执行查询语句,查看是否成功转账,数据是否发生更改:
执行如下语句,查询结果如图:
select*
fromicbc_card
select*
fromcampus_card
可以看出,转账成功执行,学号为********的学生的校园卡余额从5元增加了200元变为250元,而银行卡余额也成功减少200元,从1000元变为800元。
2.针对本题的数据库和表,分别用具体的例子展现四种数据不一致问题:
丢失修改、读脏数据、不可重复读和幻读(删除和插入)。
(40分,每种数据不一致10分)
第一种情况:
丢失修改
事务A代码如下,执行结果如图:
begintransactiona
declare@balance1decimal(10,2)
select@balance1=balancefrom
icbc_cardwherestudcardid='
set@balance1=@balance1+50
updateicbc_card
setbalance=@balance1
wherestudcardid='
committransactiona
go
fromicbc_card
学号为********的学生的银行卡里原先的余额是1000元,在执行完事务A后,可以看到,表里的数据更改为事务A所更新的余额增加50元,成为1050元。
事务B代码如下,执行结果如图:
begintransactionb
declare@balancedecimal(10,2)
select@balance=balance
fromicbc_cardwherestudcardid='
waitfordelay'
00:
05'
set@balance=@balance+100
updateicbc_card
setbalance=@balance
committransactionb
fromicbc_card
可以看到,在执行完事务B后,由于设置了waitfordelay所以事务B对学号为********的记录的修改增加余额100元的结果为1100元,覆盖了事务A的修改,即产生了丢失修改,该过程也是一个并行执行的过程,属于并发控制。
第二种情况:
读脏数据
代码如下,执行结果如图:
begintrana
declare@xdecimal(10,2)
select@x=balance
set@x=@x+100
setbalance=@x
begintranb
committranb
waitfordelay'
08'
rollback
可以看出,在执行完事务A后,由于事务A更新了学号为********的学生的银行卡的余额,给其余额增加100元,所以执行事务B查询学号为********的学生的银行卡的余额结果变为1100元,可是事务A在等待了8秒后执行rollback回滚操作,所以数据库中学号为********的学生的银行卡的余额变为1000元,可是事务B读取到的学号为********的学生的银行卡的余额结果仍然是1100元,这就叫读脏数据。
第三种情况:
不可重复读
不可重复读的代码如下:
begintransaction
select*fromicbc_card
begintransaction
declare@bdecimal(10,2)
select@b=balance
setbalance=@b*2wherestudcardid='
commit
commit
执行结果如下图:
可以看出,在第一个事务读取表icbc_card的全部数据后,显示的结果为上面的结果,然后第二个事务执行了更新操作,更新了学号为********的学生的余额字段,把其余额乘以2,提交第二个事务。
然后第一个事务执行查询表icbc_card的全部数据,结果显示学号为********的学生的余额字段的数据不再是原先的350元,而是700元,原因是第二个事务更新了这个数据,这就是不可重复读。
第四种情况:
幻读(删除和插入)
删除的幻读:
select*
deletefromicbc_card
可以看出,在第一个事务读取表icbc_card的全部数据后,显示的结果为上面的结果,然后第二个事务执行了更新操作,删除了学号为********的学生的记录,提交第二个事务。
然后第一个事务执行查询表icbc_card的全部数据,结果显示没有学号为********的记录,原因是第二个事务删除了这个数据,这就是删除幻读。
插入的幻读:
insertintoicbc_cardvalues('
20150034'
2015003401'
可以看出,在第一个事务读取表icbc_card的全部数据后,显示的结果为上面的结果,然后第二个事务执行了更新操作,插入了学号为********的学生的记录,提交第二个事务。
然后第一个事务执行查询表icbc_card的全部数据,结果显示增加了学号为********的记录,原因是第二个事务插入了这个数据,这就是插入幻读。
3.利用锁机制、数据库的隔离级别等,设计方案分别解决上述丢失修改、读脏数据和不可重复读(或者幻读)的数据不一致问题。
(30分,每种数据不一致10分,提示可以用sp_lock系统存储过程查看当前锁状况)
1)解决丢失修改
通过设置X锁
事务A代码如下:
begintransactiona
declare@bdecimal(10,2)
select@b=balance
fromicbc_cardwith(xlock)
setbalance=@b+200wherestudcardid='
可以看出,事务A更新了icbc_card表里的学号为********的学生的余额字段,给其增加200,查询结果为1200,
然后我们执行事务B:
begintransactionb
declare@adecimal(10,2)
select@a=balance
fromicbc_cardwith(xlock)wherestudcardid='
setbalance=@a+100wherestudcardid='
执行结果如下:
可以看出,事务B更新了icbc_card表里的学号为********的学生的余额字段,给其增加100,查询结果为1300,解决了丢失修改的问题,通过设置X锁。
2)解决读脏数据
通过设置数据库隔离级别和设置holdlock保持锁来解决这个这个问题
代码如下:
updateicbc_cardwith(xlock)
setbalance=balance-200
waitfordelay'
rollback
settranisolationlevelreaduncommitted
select*fromicbc_cardwith(holdlock)
执行结果如下图:
可以看到,第一个事务更新了学号为********的学生的银行卡余额,而事务二查询学号为********的学生的银行卡余额时查询结果显示的数据是事务一执行前的数据,没有发生变化。
然后在事务一rollback后,再次查询相关数据,结果如下面的图,发现查询结果未发生变化,说明解决了读脏数据。
3)解决不可重复读
begintran
declare@b1Decimal(10,2)
declare@b2Decimal(10,2)
select@b1=balancefromcampus_cardwith(holdlock)
print('
第一次数据:
'
+convert(varchar,@b1))
waitfordelay'
select@b2=balancefromcampus_cardwith(holdlock)
+convert(varchar,@b2))
updatecampus_cardwith(xlock)
setbalance=balance+100
03'
可以看出,不可重复读得到了解决。
4.构造一个出现死锁的情形。
(10分)
构造死锁的代码如下:
事务一:
select*fromcampus_cardwith(tablockx)
select*fromicbc_cardwith(tablockx)
事务二:
可以看出,发生了死锁。
5.利用dbcclog命令查看student数据库的事务日志。
命令如下,执行如图;
dbcclog(student)
二.实验中出现的问题以及解决方案(对于未解决问题请将问题列出来)
在实验中展示丢失修改的过程中,发现并发执行的两个事务,执行的结果显示并没有满足丢失修改的定义,在仔细检查了代码后,发现是waitfordelay设置错误了,在更改了这个函数后,再次运行,成功展示了丢失修改的结果。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 西工大 数据库 实验 报告