lOMoARcPSD|45315597
ng dn thc hành CSDL
BÀI THỰC HÀNH SỐ 7:
Sử dụng Transaction
1. SỬ DỤNG TRANSACTION ......................................................................................................................... 2
1.1. Khái niệm transaction :............................................................................................................................... 2
1.2. Tại sao phải dùng transaction ? ................................................................................................................... 2
1.3. Khai báo và sử dụng transaction : ................................................................................................................ 2
1.4. Transaction lồng nhau : .............................................................................................................................. 4
1.5. Kiểm tra lỗi khi xây dựng transaction .......................................................................................................... 7
2. ROLLBACK MỘT PHẦN TRANSACTION .................................................................................................. 7
2.1. Đặt vấn đề : ............................................................................................................................................... 8
2.2. Các câu lệnh và cú pháp ............................................................................................................................. 8
2.3. Liên hệ các tính chất của transaction ............................................................................................................ 9
2.4. Khi nào dùng rollback một phần ................................................................................................................ 10
2.4.1. Trường hợp 1 - Các thành phần có sự cùng phụ thuộc .......................................................................................... 10
2.4.2. Trường hợp 2 – Kiểm tra ràng buộc tốn kém ....................................................... 12
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
1. S DNG TRANSACTION
1.1. Khái nim transaction :
Giao tác (transaction) 1 tp hp th t các thao tác (statement) truy xut d liu trên CSDL
thành 1 đơn vị công vic logic (xem là 1 thao tác nguyên t), chuyn CSDL t trng thái nht quán này
sang trng thái nht quán khác.
ài
Ví d : Ngân hàng thc hin chuyn tin t t khon A sang tài khon B, cn thc hin hai công vic : tr tin của A, tăng
tin ca B. Hai công vic này hoc c hai thành công hoc không có công vic nào thành công (nếu mt công vic vì lý do
nào đó không thực hin thành công thì trạng thái ban đầu trước khi chuyn tin phải được khôi phục để bo toàn d liu).
Khi đó việc chuyn tin cần được đặt vào mt giao tác.
Chú ý : khi ta viết mt thao tác (statement) trong SQL Server, nếu không có ch th nào khác, thao
tác này là mt transaction.
1.2. Ti sao phi dùng transaction ?
Dùng khái nim giao tác khi x lý các vấn đề liên quan đến truy xut d liệu đồng thi. Có nhng x
trên CSDL được thc hin bng nhiu thao tác liên tiếp nhau, tp hp các thao tác này phải được xem
là mt thao tác nguyên t để đảm bo tính nht quán ca d liu sau khi thc hiện, nghĩa là, hoặc tt
c đưc thc hin thành công, hoặc không có thao tác nào được thc hin tp hp các thao tác này
đưc viết thành mt transaction.
Ví d: Stored procedure thc hin vic thêm mt hc sinh vào lp
Nếu bước 2 ca stored proc thc hin không thành công thì d liu trong CSDL có còn nht quán
không?
1.3. Khai báo và s dng transaction :
Các lnh liên quan :
- Bắt đầu transaction :
begin tran / begin transaction
- Hoàn tt transaction :
commit/ commit tran / commit transaction
--
B
ư
c 1
Insert
into
values
(
‘hs01
’,
’Nguyen V A
’,1)
--
B
ư
c 2
Update
Lop
Set
SiSo = SiSo +1
lOMoARcPSD| 45315597
H
ướng dn thc hành CSDL
- Quay lui transaction :
rollback / rollback tran / rollback transaction
- Đánh dấu savepoint trong transaction :
save transaction tên_savepoint
- Biến @@trancount : cho biết s transaction hiện đang thực hiện (chưa được kết thúc vi rollback
hay commit) trong connection hin hành.
Ghi chú :
- lnh rollback tran + tên_savepoint có tác dụng quay lui giao tác đến v trí đặt savepoint tương
ng (không có tác dng kết thúc transaction), các khóa (lock) được đặt khi thc hin các thao tác
nm
trong phn b rollback s đưc m ra. (xem ROLLBACK MT PHN TRANSACTION)
- Khi khai báo transaction tường minh, phải đảm bo rằng sau đó nó được rollback hoc commit
ng minh, nếu không, transaction s tiếp tc tn ti và chiếm gi tài nguyên, ngăn trở s thc
hin
ca các transaction khác.
- Lnh rollback ch có tác dng quay lui các thao tác trên CSDL (thêm, xóa, sa). Các câu
lnh khác, chng hn lnh gán, s không b nh hưng bi lnh rollback.
Các ví d : Cho bng d liệu bên dưới. Hãy cho biết giá tr ti các ô màu vàng sau khi thc hiện (độc lp)
các transaction trong các ví d sau:
MaTS
TuaSach
Tacgia
1
Aaa
ABC
2
Bbb
DEF
3
Ccc
GHI
Vd1 :
@@trancount = 0
Begin tran --(T1)
@@Trancount = ?
update Tuasach set Tacgia = xxx
where MaTS = 1
update TuaSach set TacGia = yyy
where MaTS =2
update TuaSach set TacGia = zzz
where MaTS =3
Commit tran --(T1)
@@trancount =?
Vd 2:
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
declare @x int set @x=3
@@trancount = 0
Begin tran --(T1)
@@trancount =?
update Tuasach set Tacgia = xxx where MaTS = 1
update TuaSach set TacGia = yyy where MaTS =2
set @x =7
Rollback --(tran)
@@trancount =?
Vd 3 :
1.4. Transaction lng nhau :
- Các transaction có th thc hin lng nhau, mục đích chủ yếu là để cho phép các stored procedure
có cha transaction có th đưc gi t nhng tiến trình đã nằm bên trong mt transaction hoc t
nhng tiến trình không nm bên trong mt transaction nào.
Ví d:
create proc sp_test begin tran --T2
as exec sp_test
begin tran --T1 --do something
--do something commit tran commit tran
- proc sp_test được gi t mt tiến trình nm bên trong một transaction (T2), do đó, transaction T1 trong
sp_test được xem là lng bên trong transaction T2.
update
Book
set
Author =
'xxx'
where
id =
'1'
;
declare
@x
int
;
update
Book
set
Author =
'yyy'
where
id =
'2'
;
set
@x=3;
Save tran
S;
print
@@trancount ;
@@trancount =?
@@trancount =0
Begin tran
;
--
(
T
1)
set
@x =7;
update
Boo
k
set
Author =
'zzz'
where
id =
'3'
;
Rollback tran
S;
Commit tran
;
--
1)
(
T
@@trancount =?
@@trancount =?
@@trancount =?
@x=?
@@trancount =?
@x =?
lOMoARcPSD| 45315597
H
ướng dn thc hành CSDL
- Chú ý trước câu lnh gi sp_test SQL Server t động ghi nh giá tr biến h thng @@tranCount, gi s
lưu vào biến @trc. Ngay sau câu lnh này, biến @trc và @@tranCount s đưc so sánh giá tr, nếu khác
nhau thì SQL Server s phát sinh li giúp biết được lnh gi stored proc có bo toàn các cp lng nhau v
transaction hay không. Đặc bit khi sp_test gi rollback thì chc chn T2 s có li và toàn b transaction đã
đưc rollback; lúc này
người dùng được thông báo để t quyết định thc hin tiếp hoc kết thúc tiến trình đang thực hin.
SQL đưa ra các qui định sau nhằm đảm bo vic thc hin ca các transaction lng nhau không làm vi
phm các tính cht ca giao tác :
- Lnh commit transaction s được xem như thuộc v transaction bắt đầu sau nht (bên trong nht)
chưa commit , cho dù nó được đi kèm với tên ca transaction bắt đầu trước (cấp ngoài hơn).
- Lnh commit transaction ca transaction con ch giảm @@trancount đi 1,không có tác dụng yêu
cu h qun tr ghi nhn chc chn những thay đổi trên CSDL mà transaction này đã làm.
- Ch có lnh commit transaction ca transaction ngoài cùng mi thc s có tác dụng này (như vậy
nếu có n transaction lng nhau thì lnh commit transaction th n mi thc s commit toàn b giao
tác).
- Ch cn có mt lnh rollback tran ( bt c cp nào) là toàn b giao tác s b rollback. Lý do có quy
luật này đó là nhằm bảo đảm ý nghĩa một đơn vị công vic lôgic bi khi có lnh gi rollback t mt cp
transaction nào đó đồng nghĩa với vic không thc hin thành công ti v trí đó. Trong một giao tác
đang xét, nếu thc hin không thành công bt k đim nào bt k cp giao tác nào, giao
tác ngoài cùng cần được khôi phc bởi đã trong nó đã tồn ti một ví trí “bị lỗi”.
- Giao tác không được lng nhau quá 32 cp.
- Các transaction lng nhau không tranh chp nhau v tài nguyên (có th chia s vi nhau các khoá
trên đơn vị d liệu được đọc/ghi). Điều này có th hiu t vic transaction lng nhau ch xy ra trên
cùng mt connection. Mà trên cùng một connection như vậy thì dĩ nhiên không có tranh chấp (bi các
thao tác s đưc thc hin tun t).
Ghi chú : Nếu có hai transaction T1, T2 thc hin trong cùng mt connection thì có hai trường hp :
+ T2 thc hin sau khi T1 kết thúc, lúc đó T1 và T2 là độc lp nhau;
+ T2 thc hiện khi T1 chưa kết thúc, khi đó T2 là giao tác con lồng bên trong T1.
Ví d 1:
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
Ví d 2 :
Ví d 3 :
declare
@x
int
;
@@trancount =0
set
@x=3;
Begin tran
;
--
(
T
1)
@@trancount =
?
update
Book
set
Author =
'xxx'
where
id =
'1'
;
update
Book
set
Author =
'yyy'
where
id =
'2'
;
begin tran
;
@@trancount =?
set
@x =7;
update
Book
set
Author =
'zzz'
where
id =
'3'
;
commit tran
;
Rollback tran
;
--
(
T
1)
@@trancount =?
@@trancount =?
declare
@x
int
;
Begin tran
;
--
(
T
1)
update
Book
set
Author =
'xxx'
where
id =
'1'
;
update
Book
set
Author =
'yyy'
where
id =
'2'
;
@@trancount =0
@@trancount =?
begin tran
T2;
@@trancount =?
update
Bo
ok
set
Author =
'zzz'
where
id =
'3'
;
rollback tran
T2;
L
i
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
1.5. Kim tra li khi xây dng transaction
Mt s lỗi thường gp sau khi thc hin 1 câu lnh trong giao tác:
o Không có quyn truy cập trên 1 đối tượng (table, stored procedure,…)
o Vi phm ràng buc toàn vn (primary key, foreign key, check, rule, các ràng
buộc được kim tra bằng trigger,…). o Deadlock.
O SQL Server tr giá tr li v trong biến toàn cc @@error.
o @@error= 0: không xy ra li
o @@error <> 0: xy ra li vi mã li là @@error
Giao tác không th t động rollback khi gp nhng li phát sinh trong
quá trình thc hin 1 câu lnh thành phn trong giao tác. Vì vy cn kim tra giá tr ca biến
@@error sau mi câu lnh thành phn trong giao tác và cn x lý nhng li (nếu có) và yêu cu
rollback giao tác một cách tường minh bng lnh rollback/rollback transaction. Ví d :
Xây dng giao tác thc hin việc thêm độc gi người ln. Giao tác này nm trong procedure
sp_ThemDocGiaNguoiLon.
7
2. ROLLBACK MT PHN TRANSACTION
Create proc
sp_ThemDocG
iaNguoiLon
@
Ten…
as
--
buoc 1 : xác đ
nh mã đ
c
gi
declare
@madg
set
@madg = 1
begin
transaction
while exists
(
select
*
from
DocGia
where
ma_docgia =
@madg)
set
@madg = @madg +1
if
(
@@error <>0
)
begin
rollback tran
return
end
--
buoc 2 : insert
vao bang docgia
insert into
DocGia
values
(
)
if
(
@@error <>0
)
begin
rollback tran
return
end
--
buoc 3 : kiem tra tuoi
if datediff
(
yy, @ngaysinh,
getdate
()) <18
begin
raiserror
(
‘Tuoi
nho hon 18
’,16,1)
rollback tran
return
end
commit transaction
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
2.1. Đặt vn đề :
Thông thường khi chúng ta rollback mt transaction thì toàn b những thao tác đã thực hiện trong transaction đó
đều b hy b. Tuy nhiên trong mt s trường hp nht đnh chúng ta có nhu cu ch hy b mt s thao tác nào
đó mà thôi (các thao tác còn lại không b hy b). Tuy nhu cầu này ít khi phát sinh nhưng Microsoft SQLServer có
h tr điu y.
2.2. Các câu lnh và cú pháp
a) Save tran stampName
Lnh này gn nhãn ti mt v trí nhất định trong transaction vi tên nhãn stampName. Tên nhãn này có th
mt biến chui hay mt hng chui. Khi là hng chui, tên nhãn không được để gia cặp nháy đơn.
Ví d :
--Đúng :
b) Rollback tran stampName
Lnh này rollback mt phn ca transaction. Các thao tác b rollback là các thao tác nm trên câu lệnh “Rollback
tran stampName” và nằm dưới câu lệnh “Save tran stampName” với tên nhãn tương ng.
Ví d :
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
Ví d này, khi chạy đến dòng lệnh “Rollback tran nhan_1”, các thao tác 3 và 4 sẽ b hy b. Trong khi y các thao
tác 1 và 2 thì không b hy bỏ. Sau đó SQLServer sẽ vn tiếp tc làm nt các thao tác 5 và 6.
Lưu ý : Câu lệnh “rollback tran nhan_1” chỉ đơn thuần làm công vic undo thao tác 3 và 4, nó không h làm chm
dứt transaction như câu lệnh “rolback tran” thông thường. Nói các khác, sau khi hy b thao tác 3 4, transaction
vn tiếp tc chạy cho đến khi gp câu lnh “rollback tran” hoặc “commit tran” thì mi kết thúc. Trong d trên,
nếu câu lnh cuối là “commit tran” thì các thao tác 1, 2, 5 và 6 s được lưu bn vững vào cơ sở d liệu. Ngược
li, nếu câu lnh cuối là “rollback tran” thì các thao tác này sẽ b hy b.
2.3. Liên h các tính cht ca transaction
Khi cho transaction rollback mt phn, ta cn liên h cht ch vi các tính cht của transaction như sau :
a) Tính nguyên t : Vic rollback mt phn transaction chc chn là vi phm tính nguyên t. Nếu s dng
8
rollback mt phần nghĩa là chấp nhn vi phm này.
b) Tình vng bn : Vic rollback mt phần không liên can gì đến tính vng bn vì nó không làm ảnh hưởng đến
phm vi ca transaction. Bt k thao tác nào nm trong phạm vi transaction mà đã được commit thì s đưc
SQLServer bảo đảm lưu bền vng vào CSDL.
c) Tình nht quán : Sau khi thc hin transaction, CSDL vn phi trong trng thái nhất quán, nghĩa là không vi
phm các ràng buc toàn vẹn. Do đó, người viết transaction khi quyết định s dng rollback mt phn thì phi
xem xét k các ràng buc toàn vẹn để bào đảm dù xy ra rollback mt phần thì cũng không vi phạm
ràng buc toàn vn nào.
d) Tính cô lp : Rollback mt phn không ảnh hưởng gì đến mc cô lp của transaction nhưng ảnh hưởng rõ rt
đến vic phát khoá và nh khoá trên các đơn vị d liệu. Cơ chế đưc mô t trong ví d sau :
Ví d : Gi s mc cô lp là Repeatable read
[1] Begin tran
[2] Read (A) [3] Read (B)
[4] Save tran nhan_1
[5] Read (C) [6] Read (D)
[7] Rollback tran nhan_1 [8] Read (E)
Begin tran
--
Thao tác 5
--
Tha
o tác 1
--
Thao tác 6
--
Thao tác 2
Commit tran
/
Rollback tra
n
Save tran
nhan_1
--
Thao tác 3
--
Thao tác 4
Rollback tran
nhan_1
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
Sau bước [6], các đơn vị d liệu đang bị khóa là : A, B, C và D.
Sau bước [7], các đơn vị d liệu đang bị khóa là : A và B. (C và D được khoá trong đon mã b rollback nên sau
khi rollback, các khoá này không còn na)
Sau bước [8], các đơn vị d liệu đang bị khóa : A, B E (Có thêm E b khóa). Các khoá trên A, B E s
đưc gi cho đến khi transaction kết thúc.
2.4. Khi nào dùng rollback mt phn
2.4.1. Trường hp 1 - Các thành phn có s cùng ph thuc
Ta thy rng hu hết các transaction đều tuân th tính nguyên t. Vic s dng rollback mt phn ch xy ra trong
nhng tình huống đặc bit tùy vào dng ý và s linh động của người xây dng transaction. Ta xét mt
mẫu transaction như sau :
Trong mu transaction tng quát trên đây, giả s rằng các đoạn code A, B và C có tính độc lp với nhau. Nghĩa
là một trong các đoạn này có th b rollback mà không ảnh hưởng đến các đoạn còn lại. Như vậy l ra
Save tran
stamp_3
C
1
Begin tra
n
If (lỗi 3)
ck tran stamp_3
Rollb
2
A
Save tran
stamp
_1
ran / Rollback tran
Commit
lỗi 1)
Save tran
stamp_2
B
lỗi 2)
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
chúng phải được viết trong 3 transactions khác nhau. Tuy nhiên gi s rằng các đoạn code A, B và C lại đều ph
thuộc vào đoạn code 1 (ví d như đo n code 1 kim tra mt ràng buộc nào đó được tha thì mi chạy các đoạn
code A, B và C). Do đó nếu viết 3 transactions riêng thì phi viết lại đoạn code 1 ba ln.
Hơn thế na, ta li gi s đon code 2 cùng lúc ph thuc vào c 3 đoạn code A, B và C (ví d như nó tổng kết
nh ng gì làm được và không làm được trong A, B và C). Lúc này, ta không còn gii pháp nào khác là phải đưa
c 5 đoạn code này vào trong 1 transaction. Đây chính là trường hp ta cn dùng rollback mt phn.
Tóm li : Dùng rollback mt phn khi
một nhóm thao tác mà các thao tác trong nhóm này độc lp với nhau (A, B, C) nhưng lại cùng ph thuc
vào mt hay mt s thao tác khác ngoài nhóm (1).
mt hay mt s thao tác nào đó (2) ph thuc vào mt nhóm thao tác khác các thao tác trong nhóm
này độc lp nhau (A, B, C).
C hai trường hp trên.
2.4.2. Trường hp 2 Kim tra ràng buc tn kém
Vic rollback mt phần thường là gii pháp thay thế cho s r nhánh logic lúc kim tra ràng buc toàn vn (nhánh
1 : Nếu tho ràng buc thì làm các thao tác x ; nhánh 2 : Nếu không tha thì làm các thao tác y). Gi s vic
kim tra ràng buc toàn vẹn trong transaction đòi hi nhiu tài nguyên (s dòng trong bng quá ln, câu
truy vn phc tp, …) thì người viết transaction th tránh thao tác kim tra này bng cách s dng rollback
mt phần như sau :
Dùng check constraint, rule hay trigger để ngăn chặn các thay đổi trên d liu làm vi phm RBTV.
Trong transaction, xem như không có vi phạm gì xy ra và c thc hin các thao tác x. Nếu l vi ph m
RBTV, c check constraint s phát li (@@error = 547) hoc các rule s phát li (@@error = 513) hoc
trigger s phát li (mã lỗi do người viết trigger quy định). Lúc đó trong transaction ch c n kim tra giá tr
tương ứng ca @@error và cho rollback các thao tác x (ch x mà thôi Æ rollback mt
phn) ri thc hin các thao tác y.
Ví d c th
Cho lược đồ cơ sở d liu quản lý đơn đặt hàng như sau :
lOMoARcPSD|45315597
H
ướng dn thc hành CSDL
Stored proc sau đây thực hin vic xut hàng cho mt đơn đặt hàng đồng thi lập hóa đơn cho vic xut hàng
y. Sau khi xu t hàng xong, đơn đặt hàng s trạng thái “đã xuất”. Với mi chi tiết đơn đt hàng, nếu còn
hàng thì xut và chi tiết ấy được gán trạng thái là “đã xuất” và phát sinh một chi tiết hoá đơn tương ứng. Ngược
li nếu hết hàng ri thì chi tiết đơn đặt hàng y vn trạng thái “chưa xuất”. Nếu tt c các chi tiết ca mt
đơn đặt hàng đều không có hàng để xuất thì đơn đặt hàng đó có trạng thái là “đã hủy”.
Create proc xuLyDonDatHang @maDonDatHang varchar(10)
As
If @maDonDatHang = ‘’ Begin
Print ‘Ma don dat hang phai khac rong’ Return
End
Begin tran
Set transaction isolation level Serializable
lOMoARcPSD| 45315597
H
ướng dn thc hành CSDL
If not exists(select * from donDatHang where maDonDatHang = @maDonDatHang and trangThai=0)
Begin
Print ‘Don dat hang khong ton tai hoac da duoc xu ly roi’
Rollback tran
Return
End
Insert into phieuXuat values(@maDonDatHang, Getdate()) If (@@error <> 0)
Begin
Print ‘Khong the them phieu xuat’ Rollback tran
return
End
Declare cur_chiTiet cursor for (select maSanPham, soLuong from chiTietDonDatHang where maDondatHang =
@maDonDatHang) Open
cur_chiTiet
Declare @maSanPham vachar(10) Declare @soLuong int
Declare @soChiTietXuat int
Set @soChiTietXuat = 0
Fetch next from cur_chiTiet into @maSanPham, @soLuong
While (@@ferch_status = 0) Begin
Save tran @maSanPham
Insert into chiTietPhieuXuat (@maDonDatHang,@maSanPham) If (@@error <> 0)
Begin
Print ‘Khong the them phieu xuat’ Rollback tran
retur
End
Update chiTietDonDatHang set trangThai = 1 where maDonDatHang = @maDonDatHang and maSanPham = @maSanPham
If (@@error <> 0) Begin
lOMoARcPSD| 45315597
H
ướng dn thc hành CSDL
Print ‘Khong cap nhat duoc trang thai chi tiet don dat hang’ Rollback tran
return
End
Update sanPham set soTon = soTon - @soLuong where maSanPham = @maSanPham
If (@@error = 547)
Rollback tran @maSanPham
ElseIf (@@error <> 0)
Begin
Set @soChiTietXuat = @soChiTietXuat + 1
Print ‘Khong the them phieu xuat’ Rollback tran
End return
Else
lOMoARcPSD| 45315597
H
ướng dn thc hành CSDL
Fetch next from cur_chiTiet into @maSanPham, @soLuong
End
If (@soChiTietXuat = 0) Begin
Print ‘Toan bo don dat hang bi huy
Update donDatHang set trangThai = 2 where maDondatHang = @maDondatHang
Rollback tran
Return
End
Update donDatHang set trangThai = 1 where maDondatHang = @maDondatHang
If (@@error <> 0) Begin
Print ‘Khong cap nhat duoc trang thai don dat hang’ Rollback tran return
End
Commit tran
Go
13

Preview text:

lOMoARcPSD| 45315597
Hướng dẫn thực hành CSDL
BÀI THỰC HÀNH SỐ 7:
Sử dụng Transaction
1. SỬ DỤNG TRANSACTION ......................................................................................................................... 2
1.1. Khái niệm transaction :............................................................................................................................... 2
1.2. Tại sao phải dùng transaction ? ................................................................................................................... 2
1.3. Khai báo và sử dụng transaction : ................................................................................................................ 2
1.4. Transaction lồng nhau : .............................................................................................................................. 4
1.5. Kiểm tra lỗi khi xây dựng transaction .......................................................................................................... 7
2. ROLLBACK MỘT PHẦN TRANSACTION .................................................................................................. 7
2.1. Đặt vấn đề : ............................................................................................................................................... 8
2.2. Các câu lệnh và cú pháp ............................................................................................................................. 8
2.3. Liên hệ các tính chất của transaction ............................................................................................................ 9
2.4. Khi nào dùng rollback một phần ................................................................................................................ 10
2.4.1. Trường hợp 1 - Các thành phần có sự cùng phụ thuộc .......................................................................................... 10
2.4.2. Trường hợp 2 – Kiểm tra ràng buộc tốn kém ....................................................... 12 lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL
1. SỬ DỤNG TRANSACTION
1.1. Khái niệm transaction :
Giao tác (transaction) là 1 tập hợp có thứ tự các thao tác (statement) truy xuất dữ liệu trên CSDL
thành 1 đơn vị công việc logic (xem là 1 thao tác nguyên tố), chuyển CSDL từ trạng thái nhất quán này
sang trạng thái nhất quán khác. ài
Ví dụ : Ngân hàng thực hiện chuyển tiền từ t khoản A sang tài khoản B, cần thực hiện hai công việc : trừ tiền của A, tăng
tiền của B. Hai công việc này hoặc cả hai thành công hoặc không có công việc nào thành công (nếu một công việc vì lý do
nào đó không thực hiện thành công thì trạng thái ban đầu trước khi chuyển tiền phải được khôi phục để bảo toàn dữ liệu).
Khi đó việc chuyển tiền cần được đặt vào một giao tác.
Chú ý : khi ta viết một thao tác (statement) trong SQL Server, nếu không có chỉ thị nào khác, thao
tác này là một transaction.
1.2. Tại sao phải dùng transaction ?
Dùng khái niệm giao tác khi xử lý các vấn đề liên quan đến truy xuất dữ liệu đồng thời. Có những xử lý
trên CSDL được thực hiện bằng nhiều thao tác liên tiếp nhau, tập hợp các thao tác này phải được xem
là một thao tác nguyên tố để đảm bảo tính nhất quán của dữ liệu sau khi thực hiện, nghĩa là, hoặc tất
cả được thực hiện thành công, hoặc không có thao tác nào được thực hiện tập hợp các thao tác này
được viết thành một transaction.
Ví dụ: Stored procedure thực hiện việc thêm một học sinh vào lớp
-- B ư c 1
Insert into HocSinh (MaHS, HoTen, MaLop)
values ( ‘hs01 ’, ’Nguyen V A ’,1)
-- B ư c 2 Update Lop Set SiSo = SiSo +1
Nếu bước 2 của stored proc thực hiện không thành công thì dữ liệu trong CSDL có còn nhất quán không?
1.3. Khai báo và sử dụng transaction : Các lệnh liên quan : - Bắt đầu transaction :
begin tran / begin transaction - Hoàn tất transaction :
commit/ commit tran / commit transaction lOMoAR cPSD| 45315597
H ướng dẫn thực hành CSDL - Quay lui transaction :
rollback / rollback tran / rollback transaction -
Đánh dấu savepoint trong transaction :
save transaction tên_savepoint -
Biến @@trancount : cho biết số transaction hiện đang thực hiện (chưa được kết thúc với rollback
hay commit) trong connection hiện hành. Ghi chú : -
lệnh rollback tran + tên_savepoint có tác dụng quay lui giao tác đến vị trí đặt savepoint tương
ứng (không có tác dụng kết thúc transaction), các khóa (lock) được đặt khi thực hiện các thao tác nằm
trong phần bị rollback sẽ được mở ra. (xem ROLLBACK MỘT PHẦN TRANSACTION) -
Khi khai báo transaction tường minh, phải đảm bảo rằng sau đó nó được rollback hoặc commit
tường minh, nếu không, transaction sẽ tiếp tục tồn tại và chiếm giữ tài nguyên, ngăn trở sự thực hiện của các transaction khác. -
Lệnh rollback chỉ có tác dụng quay lui các thao tác trên CSDL (thêm, xóa, sửa). Các câu
lệnh khác, chẳng hạn lệnh gán, sẽ không bị ảnh hưởng bởi lệnh rollback.
Các ví dụ : Cho bảng dữ liệu bên dưới. Hãy cho biết giá trị tại các ô màu vàng sau khi thực hiện (độc lập)
các transaction trong các ví dụ sau: MaTS TuaSach Tacgia 1 Aaa ABC 2 Bbb DEF 3 Ccc GHI Vd1 : @@trancount = 0 Begin tran --(T1) @@Trancount = ?
update Tuasach set Tacgia = xxx where MaTS = 1
update TuaSach set TacGia = yyy where MaTS =2
update TuaSach set TacGia = zzz where MaTS =3 Commit tran --(T1) @@trancount =? Vd 2: lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL declare @x int set @x=3 @@trancount = 0 Begin tran --(T1) @@trancount =?
update Tuasach set Tacgia = xxx where MaTS = 1
update TuaSach set TacGia = yyy where MaTS =2 set @x =7 Rol back --(tran) @@trancount =? Vd 3 :
update Book set Author = 'xxx' where id = '1' ; declare @x int ; @@trancount =? update Book @@trancount =0
Save tran set Author = 'yyy' where id = '2' ; set @x=3; S; print @@trancount ; @@trancount =?
Begin tran ; -- ( T 1) set @x =7; @@trancount =?
update Boo k set Author = 'zzz' where id = '3' ; Rollback tran S; @@trancount =? @x=?
Commit tran ; -- ( T1) @@trancount =? @x =?
1.4. Transaction lồng nhau :
- Các transaction có thể thực hiện lồng nhau, mục đích chủ yếu là để cho phép các stored procedure
có chứa transaction có thể được gọi từ những tiến trình đã nằm bên trong một transaction hoặc từ
những tiến trình không nằm bên trong một transaction nào. Ví dụ:
create proc sp_test begin tran --T2 as exec sp_test
begin tran --T1 --do something
--do something commit tran commit tran
- proc sp_test được gọi từ một tiến trình nằm bên trong một transaction (T2), do đó, transaction T1 trong
sp_test được xem là lồng bên trong transaction T2. lOMoAR cPSD| 45315597
H ướng dẫn thực hành CSDL
- Chú ý trước câu lệnh gọi sp_test SQL Server tự động ghi nhớ giá trị biến hệ thống @@tranCount, giả sử
lưu vào biến @trc. Ngay sau câu lệnh này, biến @trc và @@tranCount sẽ được so sánh giá trị, nếu khác
nhau thì SQL Server sẽ phát sinh lỗi giúp biết được lệnh gọi stored proc có bảo toàn các cấp lồng nhau về
transaction hay không. Đặc biệt khi sp_test gọi rol back thì chắc chắn T2 sẽ có lỗi và toàn bộ transaction đã được rol back; lúc này
người dùng được thông báo để tự quyết định thực hiện tiếp hoặc kết thúc tiến trình đang thực hiện.
SQL đưa ra các qui định sau nhằm đảm bảo việc thực hiện của các transaction lồng nhau không làm vi
phạm các tính chất của giao tác :
- Lệnh commit transaction sẽ được xem như thuộc về transaction bắt đầu sau nhất (bên trong nhất)
chưa commit , cho dù nó được đi kèm với tên của transaction bắt đầu trước (cấp ngoài hơn).
- Lệnh commit transaction của transaction con chỉ giảm @@trancount đi 1,không có tác dụng yêu
cầu hệ quản trị ghi nhận chắc chắn những thay đổi trên CSDL mà transaction này đã làm.
- Chỉ có lệnh commit transaction của transaction ngoài cùng mới thực sự có tác dụng này (như vậy
nếu có n transaction lồng nhau thì lệnh commit transaction thứ n mới thực sự commit toàn bộ giao tác).
- Chỉ cần có một lệnh rollback tran (ở bất cứ cấp nào) là toàn bộ giao tác sẽ bị rollback. Lý do có quy
luật này đó là nhằm bảo đảm ý nghĩa một đơn vị công việc lôgic bởi khi có lệnh gọi rollback từ một cấp
transaction nào đó đồng nghĩa với việc không thực hiện thành công tại vị trí đó. Trong một giao tác
đang xét, nếu thực hiện không thành công ở bất kỳ điểm nào ở bất kỳ cấp giao tác nào, giao
tác ngoài cùng cần được khôi phục bởi đã trong nó đã tồn tại một ví trí “bị lỗi”.
- Giao tác không được lồng nhau quá 32 cấp.
- Các transaction lồng nhau không tranh chấp nhau về tài nguyên (có thể chia sẻ với nhau các khoá
trên đơn vị dữ liệu được đọc/ghi). Điều này có thể hiểu từ việc transaction lồng nhau chỉ xảy ra trên
cùng một connection. Mà trên cùng một connection như vậy thì dĩ nhiên không có tranh chấp (bởi các
thao tác sẽ được thực hiện tuần tự).
Ghi chú : Nếu có hai transaction T1, T2 thực hiện trong cùng một connection thì có hai trường hợp :
+ T2 thực hiện sau khi T1 kết thúc, lúc đó T1 và T2 là độc lập nhau;
+ T2 thực hiện khi T1 chưa kết thúc, khi đó T2 là giao tác con lồng bên trong T1. Ví dụ 1: lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL declare @x int ; @@trancount =0 set @x=3;
Begin tran ; -- ( T 1) @@trancount = ?
update Book set Author = 'xxx' where id = '1' ;
update Book set Author = 'yyy' where id = '2' ; begin tran ; @@trancount =? set @x =7;
update Book set Author = 'zzz' where id = '3' ; commit tran ; @@trancount =?
Rollback tran ; -- ( T 1) @@trancount =? Ví dụ 2 : declare @x int ; @@trancount =0
Begin tran ; -- ( T 1) @@trancount =?
update Book set Author = 'xxx' where id = '1' ;
update Book set Author = 'yyy' where id = '2' ; begin tran T2; @@trancount =? update Bo ok
set Author = 'zzz' where id = '3' ; rollback tran T2; L ỗ i Ví dụ 3 : lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL
1.5. Kiểm tra lỗi khi xây dựng transaction
Một số lỗi thường gặp sau khi thực hiện 1 câu lệnh trong giao tác: o
Không có quyền truy cập trên 1 đối tượng (table, stored procedure,…) o
Vi phạm ràng buộc toàn vẹn (primary key, foreign key, check, rule, các ràng
buộc được kiểm tra bằng trigger,…). o Deadlock.
O SQL Server trả giá trị lỗi về trong biến toàn cục @@error.
o @@error= 0: không xảy ra lỗi
o @@error <> 0: xảy ra lỗi với mã lỗi là @@error
Giao tác không thể tự động rollback khi gặp những lỗi phát sinh trong
quá trình thực hiện 1 câu lệnh thành phần trong giao tác. Vì vậy cần kiểm tra giá trị của biến
@@error sau mỗi câu lệnh thành phần trong giao tác và cần xử lý những lỗi (nếu có) và yêu cầu
rollback giao tác một cách tường minh bằng lệnh rollback/rollback transaction. Ví dụ :
Xây dựng giao tác thực hiện việc thêm độc giả người lớn. Giao tác này nằm trong procedure sp_ThemDocGiaNguoiLon.
Create proc sp_ThemDocG iaNguoiLon @ Ten… … as
-- buoc 1 : xác đ nh mã đ c
gi declare @madg set @madg = 1 begin transaction
while exists ( select * from DocGia where ma_docgia = @madg) set @madg = @madg +1 if ( @@error <>0 ) begin rollback tran return end
-- buoc 2 : insert vao bang docgia insert into DocGia values ( … ) if ( @@error <>0 ) begin rollback tran return end
-- buoc 3 : kiem tra tuoi
if datediff ( yy, @ngaysinh, getdate ()) <18 begin
raiserror ( ‘Tuoi nho hon 18 ’,16,1) rollback tran return end … commit transaction 7
2. ROLLBACK MỘT PHẦN TRANSACTION lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL
2.1. Đặt vấn đề :
Thông thường khi chúng ta rollback một transaction thì toàn bộ những thao tác đã thực hiện trong transaction đó
đều bị hủy bỏ. Tuy nhiên trong một số trường hợp nhất định chúng ta có nhu cầu chỉ hủy bỏ một số thao tác nào
đó mà thôi (các thao tác còn lại không bị hủy bỏ). Tuy nhu cầu này ít khi phát sinh nhưng Microsoft SQLServer có hỗ trợ điều ấy.
2.2. Các câu lệnh và cú pháp a) Save tran stampName
Lệnh này gắn nhãn tại một vị trí nhất định trong transaction với tên nhãn là stampName. Tên nhãn này có thể là
một biến chuỗi hay một hằng chuỗi. Khi là hằng chuỗi, tên nhãn không được để giữa cặp nháy đơn. Ví dụ : --Đúng : b) Rollback tran stampName
Lệnh này rollback một phần của transaction. Các thao tác bị rollback là các thao tác nằm trên câu lệnh “Rollback
tran stampName” và nằm dưới câu lệnh “Save tran stampName” với tên nhãn tương ứng. Ví dụ : lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL
Begin tran -- Thao tác 5
-- Tha o tác 1 -- Thao tác 6
-- Thao tác 2 Commit tran / Rollback tra n Save tran nhan_1
-- Thao tác 3
-- Thao tác 4 Rollback tran nhan_1
Ví dụ này, khi chạy đến dòng lệnh “Rollback tran nhan_1”, các thao tác 3 và 4 sẽ bị hủy bỏ. Trong khi ấy các thao
tác 1 và 2 thì không bị hủy bỏ. Sau đó SQLServer sẽ vẫn tiếp tục làm nốt các thao tác 5 và 6.
Lưu ý : Câu lệnh “rol back tran nhan_1” chỉ đơn thuần làm công việc undo thao tác 3 và 4, nó không hề làm chấm
dứt transaction như câu lệnh “rolback tran” thông thường. Nói các khác, sau khi hủy bỏ thao tác 3 và 4, transaction
vẫn tiếp tục chạy cho đến khi gặp câu lệnh “rol back tran” hoặc “commit tran” thì mới kết thúc. Trong ví dụ trên,
nếu câu lệnh cuối là “commit tran” thì các thao tác 1, 2, 5 và 6 sẽ được lưu bền vững vào cơ sở dữ liệu. Ngược
lại, nếu câu lệnh cuối là “rollback tran” thì các thao tác này sẽ bị hủy bỏ.
2.3. Liên hệ các tính chất của transaction
Khi cho transaction rollback một phần, ta cần liên hệ chặt chẽ với các tính chất của transaction như sau :
a) Tính nguyên tố : Việc rollback một phần transaction chắc chắn là vi phạm tính nguyên tố. Nếu sử dụng 8
rollback một phần nghĩa là chấp nhận vi phạm này.
b) Tình vững bền : Việc rollback một phần không liên can gì đến tính vững bền vì nó không làm ảnh hưởng đến
phạm vi của transaction. Bất kỳ thao tác nào nằm trong phạm vi transaction mà đã được commit thì sẽ được
SQLServer bảo đảm lưu bền vững vào CSDL.
c) Tình nhất quán : Sau khi thực hiện transaction, CSDL vẫn phải ở trong trạng thái nhất quán, nghĩa là không vi
phạm các ràng buộc toàn vẹn. Do đó, người viết transaction khi quyết định sử dụng rollback một phần thì phải
xem xét kỹ các ràng buộc toàn vẹn để bào đảm dù xảy ra rollback một phần thì cũng không vi phạm
ràng buộc toàn vẹn nào.
d) Tính cô lập : Rollback một phần không ảnh hưởng gì đến mức cô lập của transaction nhưng ảnh hưởng rõ rệt
đến việc phát khoá và nhả khoá trên các đơn vị dữ liệu. Cơ chế được mô tả trong ví dụ sau :
Ví dụ : Giả sử mức cô lập là Repeatable read [1] Begin tran [2] Read (A) [3] Read (B) [4] Save tran nhan_1 [5] Read (C) [6] Read (D)
[7] Rollback tran nhan_1 [8] Read (E) lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL …
Sau bước [6], các đơn vị dữ liệu đang bị khóa là : A, B, C và D.
Sau bước [7], các đơn vị dữ liệu đang bị khóa là : A và B. (C và D được khoá trong đoạn mã bị rollback nên sau
khi rollback, các khoá này không còn nữa)
Sau bước [8], các đơn vị dữ liệu đang bị khóa là : A, B và E (Có thêm E bị khóa). Các khoá trên A, B và E sẽ
được giữ cho đến khi transaction kết thúc.
2.4. Khi nào dùng rollback một phần
2.4.1. Trường hợp 1 - Các thành phần có sự cùng phụ thuộc
Ta thấy rằng hầu hết các transaction đều tuân thủ tính nguyên tố. Việc sử dụng rollback một phần chỉ xảy ra trong
những tình huống đặc biệt tùy vào dụng ý và sự linh động của người xây dựng transaction. Ta xét một mẫu transaction như sau :
Save tran stamp_3 C Begin tra n 1 If (lỗi 3)
Rollb ck tran stamp_3 2
Save tran stamp _1 A
Commit ran / Rollback tran lỗi 1)
Save tran stamp_2 B lỗi 2)
Trong mẫu transaction tổng quát trên đây, giả sử rằng các đoạn code A, B và C có tính độc lập với nhau. Nghĩa
là một trong các đoạn này có thể bị rollback mà không ảnh hưởng đến các đoạn còn lại. Như vậy lẽ ra lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL
chúng phải được viết trong 3 transactions khác nhau. Tuy nhiên giả sử rằng các đoạn code A, B và C lại đều phụ
thuộc vào đoạn code 1 (ví dụ như đoạ n code 1 kiểm tra một ràng buộc nào đó được thỏa thì mới chạy các đoạn
code A, B và C). Do đó nếu viết 3 transactions riêng thì phải viết lại đoạn code 1 ba lần.
Hơn thế nữa, ta lại giả sử đoạn code 2 cùng lúc phụ thuộc vào cả 3 đoạn code A, B và C (ví dụ như nó tổng kết
nhữ ng gì làm được và không làm được trong A, B và C). Lúc này, ta không còn giải pháp nào khác là phải đưa
cả 5 đoạn code này vào trong 1 transaction. Đây chính là trường hợp ta cần dùng rollback một phần.
Tóm lại : Dùng rollback một phần khi
• Có một nhóm thao tác mà các thao tác trong nhóm này độc lập với nhau (A, B, C) nhưng lại cùng phụ thuộc
vào một hay một số thao tác khác ngoài nhóm (1).
• Có một hay một số thao tác nào đó (2) phụ thuộc vào một nhóm thao tác khác mà các thao tác trong nhóm
này độc lập nhau (A, B, C).
• Cả hai trường hợp trên.
2.4.2. Trường hợp 2 – Kiểm tra ràng buộc tốn kém
Việc rollback một phần thường là giải pháp thay thế cho sự rẽ nhánh logic lúc kiểm tra ràng buộc toàn vẹn (nhánh
1 : Nếu thoả ràng buộc thì làm các thao tác x ; nhánh 2 : Nếu không thỏa thì làm các thao tác y). Giả sử việc
kiểm tra ràng buộc toàn vẹn trong transaction đòi hỏi nhiều tài nguyên (số dòng trong bảng quá lớn, câu
truy vấn phức tạp, …) thì người viết transaction có thể tránh thao tác kiểm tra này bằng cách sử dụng rollback một phần như sau :
• Dùng check constraint, rule hay trigger để ngăn chặn các thay đổi trên dữ liệu làm vi phạm RBTV.
• Trong transaction, xem như không có vi phạm gì xảy ra và cứ thực hiện các thao tác x. Nếu lỡ vi phạ m
RBTV, các check constraint sẽ phát lỗi (@@error = 547) hoặc các rule sẽ phát lỗi (@@error = 513) hoặc
trigger sẽ phát lỗi (mã lỗi do người viết trigger quy định). Lúc đó trong transaction chỉ cầ n kiểm tra giá trị
tương ứng của @@error và cho rollback các thao tác x (chỉ x mà thôi Æ rollback một
phần) rồi thực hiện các thao tác y. Ví dụ cụ thể
Cho lược đồ cơ sở dữ liệu quản lý đơn đặt hàng như sau : lOMoARcPSD| 45315597
H ướng dẫn thực hành CSDL
Stored proc sau đây thực hiện việc xuất hàng cho một đơn đặt hàng đồng thời lập hóa đơn cho việc xuất hàng
ấy. Sau khi xuấ t hàng xong, đơn đặt hàng sẽ có trạng thái là “đã xuất”. Với mỗi chi tiết đơn đặt hàng, nếu còn
hàng thì xuất và chi tiết ấy được gán trạng thái là “đã xuất” và phát sinh một chi tiết hoá đơn tương ứng. Ngược
lại nếu hết hàng rồi thì chi tiết đơn đặt hàng ấy vẫn có trạng thái là “chưa xuất”. Nếu tất cả các chi tiết của một
đơn đặt hàng đều không có hàng để xuất thì đơn đặt hàng đó có trạng thái là “đã hủy”.
Create proc xuLyDonDatHang @maDonDatHang varchar(10) As
If @maDonDatHang = ‘’ Begin
Print ‘Ma don dat hang phai khac rong’ Return End Begin tran
Set transaction isolation level Serializable lOMoAR cPSD| 45315597
H ướng dẫn thực hành CSDL
If not exists(select * from donDatHang where maDonDatHang = @maDonDatHang and trangThai=0) Begin
Print ‘Don dat hang khong ton tai hoac da duoc xu ly roi’ Rollback tran Return End
Insert into phieuXuat values(@maDonDatHang, Getdate()) If (@@error <> 0) Begin
Print ‘Khong the them phieu xuat’ Rollback tran return End
Declare cur_chiTiet cursor for (select maSanPham, soLuong from chiTietDonDatHang where maDondatHang = @maDonDatHang) Open cur_chiTiet
Declare @maSanPham vachar(10) Declare @soLuong int Declare @soChiTietXuat int Set @soChiTietXuat = 0
Fetch next from cur_chiTiet into @maSanPham, @soLuong
While (@@ferch_status = 0) Begin Save tran @maSanPham
Insert into chiTietPhieuXuat (@maDonDatHang,@maSanPham) If (@@error <> 0) Begin
Print ‘Khong the them phieu xuat’ Rollback tran retur End
Update chiTietDonDatHang set trangThai = 1 where maDonDatHang = @maDonDatHang and maSanPham = @maSanPham If (@@error <> 0) Begin lOMoAR cPSD| 45315597
H ướng dẫn thực hành CSDL
Print ‘Khong cap nhat duoc trang thai chi tiet don dat hang’ Rollback tran return End
Update sanPham set soTon = soTon - @soLuong where maSanPham = @maSanPham If (@@error = 547) Rollback tran @maSanPham ElseIf (@@error <> 0) Begin
Set @soChiTietXuat = @soChiTietXuat + 1
Print ‘Khong the them phieu xuat’ Rollback tran End return Else lOMoAR cPSD| 45315597
H ướng dẫn thực hành CSDL
Fetch next from cur_chiTiet into @maSanPham, @soLuong End If (@soChiTietXuat = 0) Begin
Print ‘Toan bo don dat hang bi huy’
Update donDatHang set trangThai = 2 where maDondatHang = @maDondatHang Rollback tran Return End
Update donDatHang set trangThai = 1 where maDondatHang = @maDondatHang If (@@error <> 0) Begin
Print ‘Khong cap nhat duoc trang thai don dat hang’ Rollback tran return End Commit tran Go 13