Bạn Tìm Gì Hôm Nay ...?
Tất cả đều có chỉ trong 1 nốt nhạc !
Nếu cần hỗ trợ chi tiết gọi 1900 9477
SQL Server nói riêng và các database quan hệ nói chung là dạng database có độ nhất quán dữ liệu cao nhất. Dữ liệu trong database luôn ở dạng consistency tại mọi thời điểm. Nghĩa là với cùng một dữ liệu thì không thể có việc đọc ghi tại cùng một thời điểm. Việc đọc ghi cùng một dữ liệu sẽ dẫn tới hiện tượng lock lẫn nhau để đảm bảo dữ liệu được consistency. Điều đó dẫn tới một số tình huống sau:
Lock thực ra không đáng sợ, nó chỉ ảnh hưởng một phần tới performance khi các lệnh thực hiện đồng thời có thể sẽ phải đợi nhau một cách tuần tự. Nhưng deadlock thì khác, nó dẫn tới không lệnh nào được thực hiện. Vậy deadlock là gì?
Deadlock là hiện tượng tranh chấp tài nguyên giữa hai hay nhiều lệnh trong đó lệnh này giữ tài nguyên mà lệnh kia cần dẫn tới việc không lệnh nào có thể kết thúc để giải phóng tài nguyên. Điều đó thể hiện qua hình minh họa:
Trong trường hợp này: Giao dịch T1 giữ được tài nguyên R1, nhưng cần tài nguyên R2 để kết thúc và giải phóng R1, nhưng R2 lại đang bị T2 giữ và T2 cần R1 để kết thúc và sau đó giải phóng R2. Trong trường hợp này cả T1 và T2 không thể kết thúc. Trường hợp này trong SQL Server sẽ phải chọn kill một trong hai giao dịch.
Một transaction được thực thi và hoàn tất khi và chỉ khi tất cả các lệnh trong một transaction được hoàn tất.
Deadlock trong database sẽ chỉ xảy ra khi có nhiều hơn một tài nguyên cần phải bị chiếm giữa hoàn tất giao dịch. Xét một câu trúc DB đơn giản như sau:
Thực hiện hai giao dịch đồng thời:
static void Main( string[] args )
{
Console.ReadKey();
Console.WriteLine( "Start" );
using ( TransactionScope transaction = new TransactionScope() )
{
using ( SqlConnection con = new SqlConnection( connectionString2 ) )
{
con.Open();
string cmd = "Insert Into A(Name) Values('Z')";
SqlCommand command = new SqlCommand( cmd, con );
command.ExecuteNonQuery();
Thread.Sleep( 5000 );
cmd = "Insert Into B(Name) Values('X')";
command = new SqlCommand( cmd, con );
command.ExecuteNonQuery();
}
transaction.Complete();
}
Console.WriteLine( "Finish!" );
Console.ReadKey();
}
Transaction 2:
static void Main( string[] args )
{
Console.ReadKey();
Console.WriteLine( "Start" );
using ( TransactionScope transaction = new TransactionScope() )
{
using ( SqlConnection con = new SqlConnection( connectionString2 ) )
{
con.Open();
string cmd = "Select * From B";
SqlCommand command = new SqlCommand( cmd, con );
SqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
Console.WriteLine( (string)reader[ "Name" ] );
}
reader.Close();
Console.WriteLine( "-------" );
cmd = "Select * From A";
command = new SqlCommand( cmd, con );
reader = command.ExecuteReader();
while ( reader.Read() )
{
Console.WriteLine( (string)reader[ "Name" ] );
}
}
transaction.Complete();
}
Console.WriteLine( "Finish!" );
Console.ReadKey();
}
Ở đây, trong giao dịch 1 ta để thêm lệnh Thread.Sleep(5000) để quan sát hiện tượng deadlock được rõ hơn. Thực hiện hai chương trình gần như đồng thời, chương trình của giao dịch 1 chạy trước, ngay sau là chương trình giao dịch 2 thì sẽ ghi nhận deadlock exception xảy ra:
Nguyên nhân xảy ra:
Như vậy cả T1 và T2 đều lock lẫn nhau và không thằng nào thoát ra được. Dẫn tới SQL Server buộc phải kill một trong hai giao dịch, trong trường hợp này là giao dịch T2 bị kill, T1 thực hiện bình thường.
Một điều cần lưu ý là nếu hai giao dịch trên chỉ có các lệnh insert và update, delete mà không có các lệnh select thì khả năng deadlock thấp hơn rất nhiều. Vì các lệnh insert và update chỉ lock row, do đó việc tranh chấp dẫn tới deadlock khó xảy ra.
Không đảm bảo có thể loại bỏ hoàn toàn deadlock, nhưng áp dụng các chiến lược sau sẽ giúp việc xảy ra deadlock ít xảy ra hơn:
Transaction 1:
CREATE PROCEDURE [dbo].[Test1]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRANSACTION TEST1
-- Insert statements for procedure here
Insert Into A(Name) Values('Zz')
WAITFOR DELAY '00:00:10';
Insert Into B(Name) Values('Xz')
COMMIT TRANSACTION TEST1
END
Transaction 2:
CREATE PROCEDURE [dbo].[Test2]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRANSACTION TEST2
select *
from B
select *
from A
COMMIT TRANSACTION TEST2
END
Mặc dù store procedure Test1 có thời gian delay lâu hơn 10 giây, nhưng hiện tượng deadlock vẫn không xảy ra.
Việc sử dụng transaction cần phải hiểu ý nghĩa và không nên lạm dụng. Giả sử để thực hiện được một tính năng cần tác động tới hai hoặc nhiều bảng, vậy có nhất thiết phải gói tất cả các lệnh vào một giao dịch? Để trả lời chính xác thì phải hiểu thế nào là một giao dịch.
Một giao dịch là chuỗi các hành động mà nếu một trong các hành động không hoàn thành thì toàn bộ các hành động khác cũng phải không được hoàn thành. Xét ví dụ kinh điển về giao dịch rút tiền:
Lệnh 1: Thực hiện lệnh update trừ tiền
Lệnh 2: Xác nhận người dùng nhận được tiền
Như vậy nếu lệnh 1 trừ tiền xong, nhưng lệnh xác nhận người dùng nhận được tiền không thực thi được thì lệnh 1 cũng phải không được thực hiện mà phải rollback về trạng thái đầu.
Nhưng nếu có một nghiệp vụ cập nhật thông tin hồ sơ cho học sinh khác như sau:
Lệnh 1: cập nhật tuổi bảng profile
Lệnh 2: cập nhật điểm bảng lớp học
Rõ ràng để thực hiện nghiệp vụ trên cần phải thực hiện cả hai hành động trên, nhưng không có nghĩa là nếu lệnh 2 không thành công thì lệnh 1 không được thực hiện, vì sau đó ta hoàn toàn có thể kiểm tra là lệnh 1 mà thực thi rồi thì chỉ thực thi lệnh 2, việc không thực thi đồng thời hai lệnh trên không làm sai nghiệp vụ của hệ thống.
Do đó khi thực hiện giao dịch cần phải rất thận trọng và phải có đánh giá tổng thể xem việc thực thi đó có bị xung đột nhau hay không? Việc sử dụng tràn lan transation, thậm chí cả với các lệnh select đọc dữ liệu là vô cùng tai hại và đó là thể hiện sự máy móc, thiếu hiểu biết trong lập trình.
Lock trong CSDL là vô cùng quan trọng, nó đảm bảo tính consistency database. Nhưng trong một số trường hợp cần hiệu năng cao thì có thể sử dụng một số mode đặc biệt để đọc, ghi mà không cần lock dữ liệu:
P.A Việt Nam cung cấp đa dạng các Plan Hosting đáp ứng yêu cầu của khách hàng
Hosting Phổ Thông
Hosting Chất Lượng Cao
Tham khảo các ưu đãi: https://www.pavietnam.vn/vn/tin-khuyen-mai/