Hệ thống quản lý cơ sở dữ liệu - Kiểm soát đồng bộ: Hướng dẫn cho người mới bắt đầu

Xin chào các nhà thuật toán tương lai! Hôm nay, chúng ta sẽ bắt đầu một hành trình thú vị vào thế giới Kiểm soát Đồng bộ trong Hệ thống Quản lý Cơ sở Dữ liệu (DBMS). Đừng lo lắng nếu bạn là người mới; tôi sẽ là hướng dẫn viên thân thiện của bạn, và chúng ta sẽ khám phá chủ đề này từng bước một. Vậy, hãy lấy một tách cà phê, và chúng ta cùng nhảy vào!

DBMS - Concurrency Control

什么是 đồng bộ kiểm soát?

Trước khi chúng ta đi vào chi tiết, hãy hiểu đồng bộ kiểm soát là gì. Hãy tưởng tượng một nhà hàng忙禄, nhiều nhân viên phục vụ đang cố gắng nhận订单 và phục vụ thức ăn cùng một lúc. Nếu không có sự phối hợp hợp lý, sẽ xảy ra hỗn loạn! Tương tự, trong cơ sở dữ liệu, nhiều người dùng hoặc quy trình có thể cố gắng truy cập và sửa đổi dữ liệu cùng một lúc. Đồng bộ kiểm soát giống như đầu bếp chính, đảm bảo mọi thứ diễn ra mượt mà mà không có xung đột.

Bây giờ, hãy cùng khám phá các phương pháp chính được sử dụng để kiểm soát đồng bộ trong DBMS.

Các giao thức dựa trên khóa

Hiểu về khóa

Khóa giống như những biển báo "Đừng làm phiền" trên cửa của phòng khách sạn. Khi một giao dịch cần truy cập dữ liệu, nó đặt một khóa lên nó, nói với người khác, "Hey, tôi đang làm việc ở đây!"

Các loại khóa

Loại Khóa Mô tả Trường hợp sử dụng
Khóa Chia sẻ (S) Cho phép nhiều giao dịch đọc dữ liệu Đọc dữ liệu mà không sửa đổi
Khóa Độc quyền (X) Chỉ một giao dịch có thể giữ khóa này Ghi hoặc cập nhật dữ liệu

Giao thức Two-Phase Locking (2PL)

Giao thức này giống như một điệu nhảy với hai bước chính:

  1. Giai đoạn Tăng trưởng: Mở khóa, không释 放 bất kỳ khóa nào.
  2. Giai đoạn Co lại:释 放 khóa, không mở khóa bất kỳ khóa nào.

Hãy xem một ví dụ đơn giản:

BEGIN TRANSACTION;
-- Giai đoạn Tăng trưởng
LOCK TABLE users IN EXCLUSIVE MODE;
UPDATE users SET balance = balance - 100 WHERE id = 1;
LOCK TABLE transactions IN EXCLUSIVE MODE;
INSERT INTO transactions (user_id, amount) VALUES (1, -100);
-- Giai đoạn Co lại
UNLOCK TABLE users;
UNLOCK TABLE transactions;
COMMIT;

Trong ví dụ này, chúng ta trước tiên mở khóa các bảng cần thiết, thực hiện các thao tác của mình, và sau đó释 放 các khóa trước khi cam kết giao dịch.

Đ死锁: Điệu nhảy sai lầm

Hãy tưởng tượng hai vũ công đang chờ đợi nhau để di chuyển. Đó là một deadlocks! Trong cơ sở dữ liệu, điều này xảy ra khi hai giao dịch đang chờ đợi nhau để释 放 một khóa.

Để ngăn chặn deadlocks, chúng ta sử dụng các kỹ thuật như:

  1. Đếm ngược: Nếu một giao dịch chờ đợi quá lâu, nó sẽ bị hoàn tác.
  2. Phát hiện deadlock: Hệ thống tích cực tìm kiếm và giải quyết deadlocks.

Các giao thức dựa trên thời gian

Bây giờ, hãy chuyển sang các giao thức dựa trên thời gian. Những giao thức này giống như việc cấp một vé duy nhất với thời gian cho mỗi giao dịch khi nó vào hệ thống.

Giao thức Basic Timestamp Ordering (TO)

Trong giao thức này, chúng ta sử dụng thời gian để xác định thứ tự của các thao tác xung đột. Nó giống như phục vụ khách hàng dựa trên thời gian họ đến nhà hàng.

Dưới đây là cách nó hoạt động:

  1. Mỗi mục dữ liệu X có hai giá trị thời gian:
  • W-timestamp(X): Thời gian lớn nhất của bất kỳ giao dịch nào đã ghi thành công X.
  • R-timestamp(X): Thời gian lớn nhất của bất kỳ giao dịch nào đã đọc thành công X.
  1. Đối với một giao dịch T cố gắng đọc X:
  • Nếu TS(T) < W-timestamp(X), T quá muộn và phải bị hủy bỏ và khởi động lại.
  • Ngược lại, cho phép T đọc X và đặt R-timestamp(X) thành max(R-timestamp(X), TS(T)).
  1. Đối với một giao dịch T cố gắng ghi X:
  • Nếu TS(T) < R-timestamp(X) hoặc TS(T) < W-timestamp(X), T quá muộn và phải bị hủy bỏ và khởi động lại.
  • Ngược lại, cho phép T ghi X và đặt W-timestamp(X) thành TS(T).

Hãy xem một ví dụ:

class DataItem:
def __init__(self):
self.value = None
self.r_timestamp = 0
self.w_timestamp = 0

def read(transaction, data_item):
if transaction.timestamp < data_item.w_timestamp:
print(f"Giao dịch {transaction.id} quá muộn để đọc. Hủy bỏ...")
abort(transaction)
else:
print(f"Giao dịch {transaction.id} đọc giá trị: {data_item.value}")
data_item.r_timestamp = max(data_item.r_timestamp, transaction.timestamp)

def write(transaction, data_item, new_value):
if (transaction.timestamp < data_item.r_timestamp or
transaction.timestamp < data_item.w_timestamp):
print(f"Giao dịch {transaction.id} quá muộn để ghi. Hủy bỏ...")
abort(transaction)
else:
print(f"Giao dịch {transaction.id} ghi giá trị: {new_value}")
data_item.value = new_value
data_item.w_timestamp = transaction.timestamp

def abort(transaction):
print(f"Giao dịch {transaction.id} bị hủy bỏ và sẽ được khởi động lại.")

Trong ví dụ này, chúng ta đã triển khai các thao tác đọc và ghi cơ bản theo giao thức timestamp ordering. Hệ thống kiểm tra thời gian trước khi cho phép các thao tác và cập nhật chúng tương ứng.

Quy tắc Ghi Thomas: Một kỹ thuật tối ưu hóa thông minh

Quy tắc Ghi Thomas giống như cho phép một người chạy nhanh hơn vượt qua người chạy chậm hơn trong một cuộc đua. Nó cho phép chúng ta bỏ qua một số thao tác ghi "quá muộn" mà không hủy bỏ giao dịch.

Dưới đây là cách nó hoạt động:

Nếu TS(T) < W-timestamp(X), thay vì hủy bỏ T, chúng ta đơn giản là bỏ qua thao tác ghi này. Điều này an toàn vì giá trị được ghi đã lỗi thời.

Hãy sửa đổi hàm ghi để bao gồm Quy tắc Ghi Thomas:

def write_with_thomas_rule(transaction, data_item, new_value):
if transaction.timestamp < data_item.r_timestamp:
print(f"Giao dịch {transaction.id} quá muộn để ghi. Hủy bỏ...")
abort(transaction)
elif transaction.timestamp < data_item.w_timestamp:
print(f"Giao dịch {transaction.id} bị bỏ qua do Quy tắc Ghi Thomas.")
else:
print(f"Giao dịch {transaction.id} ghi giá trị: {new_value}")
data_item.value = new_value
data_item.w_timestamp = transaction.timestamp

Kỹ thuật tối ưu hóa này giúp giảm số lượng hủy bỏ giao dịch không cần thiết, cải thiện hiệu suất hệ thống tổng thể.

Kết luận

Uf! Chúng ta đã bao quát rất nhiều nội dung hôm nay, từ các giao thức dựa trên khóa đến các giao thức dựa trên thời gian. Nhớ rằng kiểm soát đồng bộ là về việc duy trì trật tự trong thế giới hỗn loạn của các thao tác cơ sở dữ liệu đồng thời. Nó giống như một cảnh sát giao thông tại một ngã tư đông đúc, đảm bảo mọi người đến đích an toàn mà không va chạm vào nhau.

Khi bạn tiếp tục hành trình trong thế giới cơ sở dữ liệu, bạn sẽ gặp nhiều khái niệm và kỹ thuật phức tạp hơn. Nhưng hiện tại, hãy tự động viên mình vì đã lĩnh hội các khái niệm cơ bản của kiểm soát đồng bộ!

Tiếp tục thực hành, giữ vững sự tò mò, và chúc bạn viết mã vui vẻ!

Credits: Image by storyset