25/05/2018, 09:09

Giao dịch SQL

Một khái niệm quan trọng là khái niệm giao dịch (Transaction). Các tính chất một giao dịch phải có để đảm bảo một HQTCSDL, được xây dựng trên HCSDL tương ứng, trong suốt quá trình hoạt động sẽ luôn cho một CSDL tin cậy (dữ liệu luôn nhất ...

Một khái niệm quan trọng là khái niệm giao dịch (Transaction). Các tính chất một giao dịch phải có để đảm bảo một HQTCSDL, được xây dựng trên HCSDL tương ứng, trong suốt quá trình hoạt động sẽ luôn cho một CSDL tin cậy (dữ liệu luôn nhất quán). Quản trị giao dịch nhằm đảm bảo mọi giao dịch trong hệ thống có các tính chất mà một giao dịch phải có. Một điều cần chú ý là trong các tính chất của một giao dịch, tính chất nhất quán trước hết phải được đảm bảo bởi người lập trình- người viết ra giao dịch.

Giao dịch và các tính chất của giao dịch

Một giao dịch (transaction) là một hoặc một chuỗi nhiều câu lệnh SQL được kết hợp lại với nhau thành một khối công việc. Các câu lệnh SQL xuất hiện trong giao dịch thường có mối quan hệ tương đối mật thiết với nhau và thực hiện các thao tác độc lập. Việc kết hợp các câu lệnh lại với nhau trong một giao dịch nhằm đảm bảo tính toàn vẹn dữ liệu và khả năng phục hồi dữ liệu. Trong một giao dịch, các câu lệnh có thể độc lập với nhau nhưng tất cả các câu lệnh trong một giao dịch đòi hỏi hoặc phải thực thi trọn vẹn hoặc không một câu lệnh nào được thực thi.

Các cơ sở dữ liệu sử dụng nhật ký giao dch (transaction log) để ghi lại các thay đổi mà giao dịch tạo ra trên cơ sở dữ liệu và thông qua đó có thể phục hồi dữ liệu trong trường hợp gặp lỗi hay hệ thống có sự cố.

Một giao dịch đòi hỏi phải có được bồn tính chất sau đây:

  • Tính nguyên t(Atomicity): Mọi thay đổi về mặt dữ liệu hoặc phải được thực hiện trọn vẹn khi giao dịch thực hiện thành công hoặc không có bất kỳ sự thay đổi nào về dữ liệu xảy ra nếu giao dịch không thực hiện được trọn vẹn. Nói cách khác, tác dụng của các câu lệnh trong một giao dịch phải như là một câu lệnh đơn.
  • Tính nhất quán (Consistency):Tính nhất quan đòi hỏi sau khi giao dịch kết thúc, cho dù là thành công hay bị lỗi, tất cả dữ liệu phải ở trạng thái nhất quán (tức là sự toàn vẹn dữ liệu phải luôn được bảo toàn).
  • Tính đc lập (Isolation):Tính độc lập của giao dịch có nghĩa là tác dụng của mỗi một giao dịch phải giống như khi chỉ mình nó được thực hiện trên chính hệ thống đó. Nói cách khác, một giao dịch khi được thực thi đồng thời với những giao dịch khác trên cùng hệ thống không chịu bất kỳ sự ảnh hưởng nào của các giao dịch đó.
  • Tính bn vững (Durability):Sau khi một giao dịch đã thực hiện thành công, mọi tác dụng mà nó đã tạo ra phải tồn tại bền vững trong cơ sở dữ liệu, chodù là hệ thống có bị lỗi đi chăng nữa.

Mô hình giao dịch trong SQL

được định nghĩa dựa trên các câu lệnh xử lý giao dịch sau đây:

BEGIN TRANSACTION
: Bắt đầu một giao dịch

SAVE TRANSACTION
: Đánh dấu một vị trí trong giao dịch (gọi là điểm đánh dấu).

ROLLBACK TRANSACTION
: Quay lui trở lại đầu giao dịch hoặc một điểm đánh dấu trước đó trong giao dịch.

COMMIT TRANSACTION
: Đánh dấu điểm kết thúc một giao dịch. Khi câu lệnh này thực thi cũng có nghĩa là giao dịch đã thực hiện thành công.

ROLLBACK [WORK]
: Quay lui trở lại đầu giao dịch.

COMMIT [WORK]
: Đánh dấu kết thúc giao dịch.

Một giao dịch trong SQL được bắt đấu bởi câu lệnh

BEGIN TRANSACTION
. Câu lệnh này đánh dấu điểm bắt đầu của một giao dịch và có cú pháp như sau:
BEGIN TRANSACTION [tên_giao_tác]

Một giao dịch sẽ kết thúc trong các trường hợp sau

  • Câu lệnh
    COMMIT TRANSACTION
    (hoặc
    COMMIT WORK
    ) được thực thi. Câu lệnh này báo hiệu sự kết thúc thành công của một giao dịch. Sau câu lệnh này, một giao dịch mới sẽ được bắt đầu.
  • Khi câu lệnh
    ROLLBACK TRANSACTION
    (hoặc
    ROLLBACK WORK
    ) được thực thi để huỷ bỏ một giao dịch và đưa cơ sở dữ liệu về trạng thái như trước khi giao dịch bắt đầu. Một giao dịch mới sẽ bắt đầu sau khi câu lệnh
    ROLLBACK
    được thực thi.
  • Một giao dịch cũng sẽ kết thúc nếu trong quá trình thực hiện gặp lỗi (chẩng hạn hệ thống gặp lỗi, kết nối mạng bị “đứt”,...). Trong trường hợp này, hệ thống sẽ tự động phục hồi lại trạng thái cơ sở dữ liệu như trước khi giao dịch bắt đầu (tương tự như khi câu lệnh
    ROLLBACK
    được thực thi để huỷ bỏ một giao dịch). Tuy nhiên, trong trường hợp này sẽ không có giao dịch mới được bắt đầu.

Giao dịch dưới đây kết thúc do lệnh

ROLLBACK TRANSACTION
và mọi thay đổi vể mặt dữ liệu mà giao dịch đã thực hiện (
UPDATE
) đều không có tác dụng.
BEGIN TRANSACTION giaotac1
UPDATE monhoc SET sodvht=4 WHERE sodvht=3
UPDATE diemthi SET diemlan2=0 WHERE diemlan2 IS NULL
ROLLBACK TRANSACTION giaotac1

còn giao dịch dưới đây kết thúc bởi lệnh

COMMIT
và thực hiện thành công việc cập nhật dữ liệu trên các bảng MONHOC và DIEMTHI.
BEGIN TRANSACTION giaotac2
UPDATE monhoc SET sodvht=4 WHERE sodvht=3
UPDATE diemthi SET diemlan2=0 WHERE diemlan2 IS NULL
COMMIT TRANSACTION giaotac2

Câu lệnh:

SAVE TRANSACTION tên_điểm_dánh_dấu

được sử dụng để đánh dấu một vị trí trong giao dịch. Khi câu lệnh này được thực thi, trạng thái của cơ sở dữ liệu tại thời điểm đó sẽ được ghi lại trong nhật ký giao dịch.

Trong quá trình thực thi giao dịch có thể quay trở lại một điểm đánh dấu bằng cách sử dụng câu lệnh:

ROLLBACK TRANSACTION tên_điểm_đánh_dấu

Trong trường hợp này, những thay đổi về mặt dữ liệu mà giao dịch đã thực hiện từ điểm đánh dấu đến trước khi câu lệnh

ROLLBACK
được triệu gọi sẽ bị huỷ bỏ. Giao dịch sẽ được tiếp tục với trạng thái cơ sở dữ liệu có được tại điểm đánh dấu . Hình dưới mô tả cho ta thấy hoạt động của một giao dịch có sử dụng các điểm đánh dấu:

Hoạt động của 1 giao dịch

Sau khi câu lệnh

ROLLBACK TRANSACTION
được sử dụng để quay lui lại một điểm đánh dấu trong giao dịch, giao dịch vẫn được tiếp tục với các câu lệnh sau đó. Nhưng nếu câu lệnh này được sử dụng để quay lui lại đầu giao dịch (tức là huỷ bỏ giao dịch), giao dịch sẽ kết thúc và do đó câu lệnh
COMMIT TRANSACTION
trong trường hợp này sẽ gặp lỗi.

Câu lệnh

COMMIT TRANSACTION
trong giao dịch dưới đây kết thúc thành công một giao dịch
BEGIN TRANSACTION giaotac3
UPDATE diemthi SET diemlan2=0 WHERE diemlan2 IS NULL
SAVE TRANSACTION a
UPDATE monhoc SET sodvht=4 WHERE sodvht=3
ROLLBACK TRANSACTION a
UPDATE monhoc SET sodvht=2 WHERE sodvht=3
COMMIT TRANSACTION giaotac3

và trong ví dụ dưới đây, câu lệnh

COMMIT TRANSACTION
gặp lỗi:
BEGIN TRANSACTION giaotac4
UPDATE diemthi SET diemlan2=0 WHERE diemlan2 IS NULL
SAVE TRANSACTION a
UPDATE monhoc SET sodvht=4 WHERE sodvht=3
ROLLBACK TRANSACTION giaotac4
UPDATE monhoc SET sodvht=2 WHERE sodvht=3
COMMIT TRANSACTION giaotac4

Giao dịch lồng nhau

Các giao dịch trong SQL có thể được lồng vào nhau theo từng cấp. Điều này thường gặp đối với các giao dịch trong các thủ tục lưu trữ được gọi hoặc từ một tiến trình trong một giao dịch khác.

Ví dụ dưới đây minh hoạ cho ta trường hợp các giao dịch lồng nhau.

Ta định nghĩa bảng T như sau:

CREATE TABLE T
(
A INT PRIMARY KEY,
B INT
)

và thủ tục sp_TransEx:

CREATE PROC sp_TranEx(@a INT,@b INT)
AS
BEGIN
END
BEGIN
TRANSACTION
T1
IF NOT EXISTS (SELECT * FROM T WHERE A=@A )
INSERT INTO T VALUES(@A,@B)>
IF NOT EXISTS (SELECT * FROM T WHERE A=@A+1) 
INSERT INTO T VALUES(@A+1,@B+1)
COMMIT TRANSACTION T1

Lời gọi đến thủ tục

sp_TransEx
được thực hiện trong một giao dịch khác như sau:
BEGIN TRANSACTION T3

Trong giao dịch trên, câu lệnh

ROLLBACK TRANSACTION T3
huỷ bỏ giao dịch và do đó tác dụng của lời gọi thủ tục trong giao dịch không còn tác dụng, tức là không có dòng dữ liệu nào mới được bổ sung vào bảng T (cho dù giao dịch T1 trong thủ tục sp_tranex đã thực hiện thành công với lệnh
COMMIT TRANSACTION T1
).

Ta xét tiếp một trường hợp của một giao dịch khác trong đó có lời gọi đến thủ tục sp_tranex như sau :

BEGIN TRANSACTION EXECUTE sp_tranex 20,40
    SAVE TRANSACTION a
    EXECUTE sp_tranex 30,60
    ROLLBACK TRANSACTION a
    EXECUTE sp_tranex 40,80
    COMMIT TRANSACTION

sau khi giao dịch trên thực hiện xong, dữ liệu trong bảng T sẽ là:

A B
20 40
21 41
40 80
41 81

Như vậy, tác dụng của lời gọi thủ tục sp_tranex 30,60 trong giao dịch đã bị huỷ bỏ bởi câu lệnh

ROLLBACK TRANSACTION
trong giao dịch.

Như đã thấy trong ví dụ trên, khi các giao dịch SQL được lồng vào nhau, giao dịch ngoài cùng nhất là giao dịch có vai trò quyết định. Nếu giao dịch ngoài cùng nhất được uỷ thác (commit) thì các giao dịch được lồng bên trong cũng đồng thời uỷ thác.

Và nếu giao dịch ngoài cùng nhất thực hiện lệnh ROLLBACK thì những giao dịch lồng bên trong cũng chịu tác động của câu lệnh này (cho dù những giao dịch lồng bên trong đã thực hiện lệnh

COMMIT TRANSACTION
).
0