Tìm hiểu về các loại Khoá (Explicit Locking) trong PostgreSQL

Tìm hiểu về các loại Khoá (Explicit Locking) trong PostgreSQL

Tin ngắn hàng ngày dành cho bạn
  • Mấy hôm trước OpenAI giới thiệu Deep Research - một công cụ duyệt web để nghiên cứu và cho ra một bản tổng hợp chỉ trong vài chục phút - so với nhiều giờ làm việc đối với con người, theo như họ công bố.

    Tính năng này hiện chỉ có sẵn cho người dùng Pro. Mặc dù chưa được dùng thử, nhưng qua nhiều bài viết đều nhấn mạnh vào sự ấn tượng trước khả năng của công cụ mới này. Nếu vẫn chưa biết Deep Research làm được gì thì bạn cứ hình dung như thế này: Nói với nó "Tôi cần thông tin nghiên cứu về lượng tiêu thụ cà phê của thế giới trong năm ngoái". Thế thôi! Ngồi chờ một lúc để nó tìm kiếm và tổng hợp lại kết quả và gửi lại cho bạn một bài báo cáo chi tiết. Chà, ghê thật chứ!

    Ngay lập tức huggingface đã lên một bài viết cố gắng tái tạo lại công cụ này theo cách của họ. Chi tiết tại Open-source DeepResearch – Freeing our search agents. Và không có gì ngạc nhiên khi cả 2 đều mang hơi hướng của AI Agents.

    » Xem thêm
  • Sống đủ lâu trong thế giới Internet, bạn có thể thấy rằng mọi người ở đây khá háo hức chạy theo xu hướng và chúng lan truyền với tốc độ chóng mặt.

    Chỉ vài tháng trước, chúng ta vẫn còn kinh ngạc về trí thông minh của các mô hình ngôn ngữ lớn (LLM) có thể trả lời giống như con người, và ngay sau đó, chúng đã được cập nhật với khả năng suy nghĩ và lý luận đáng kinh ngạc. Chúng được ứng dụng rộng rãi không chỉ trong lĩnh vực lập trình. Gần đây, thuật ngữ AI Agents đã tạo nên một sự khuấy động.

    Vậy, AI Agents là gì? Trong bài viết ngắn này, tất nhiên là không thể đưa ra một định nghĩa ngắn gọn nhưng toàn diện. Bạn đọc có thể tham khảo bài viết rất chi tiết này tại đây Agents | Chip Huyền. Để dễ hình dung hơn, AI Agents có thể được coi là một người hoặc một thực thể nào đó. Bản thân các Agents được trang bị tất cả các công cụ cần thiết. Từ đó, các Agents có thể kết hợp chúng để hoàn thành một nhiệm vụ mà chúng ta giao.

    Vẫn còn hơi mơ hồ phải không? Một ví dụ thực tế là khi bạn ra lệnh cho các Agents truy cập Facebook vào lúc 8 giờ tối mỗi ngày, kiểm tra bất kỳ tin tức nổi bật nào từ bạn bè, sau đó gửi tóm tắt đến Telegram. Vậy là xong!

    » Xem thêm
  • Hôm qua đến nay, lượt truy cập tới từ Facebook tăng đột biến. Thường như thế là do ai đó chia sẻ bài viết của blog vào một nhóm nào đó.

    Cơ mà lần này là liên kết trực tiếp đến trang chủ luôn. Tò mò ghê, không biết ai chia sẻ, chia sẻ ở đâu nữa. Muốn biết để tìm hiểu "insight" ghê 🥹

    » Xem thêm

Vấn đề

Làm việc với SQL hay PostgreSQL đủ lâu nhưng có bao giờ bạn đặt câu hỏi sẽ thế nào nếu như thực hiện một lệnh SELECT và DROP trên cùng một table cùng lúc? Lệnh nào sẽ chạy trước lệnh nào sẽ chạy sau, độ ưu tiên của các câu lệnh như thế nào hay là PostgreSQL dựa vào đâu để phân mức ưu tiên? Bài viết này hôm nay tôi xin phép trình bày cách mà PostgreSQL sử dụng Khoá (Locks) để giải quyết xung đột dữ liệu như thế nào nhé.

Tại sao lại cần khoá?

PostgreSQL cung cấp nhiều chế độ khóa khác nhau để kiểm soát quyền truy cập đồng thời vào dữ liệu trong bảng. Các khoá này có thể được sử dụng để can thiệp vào các tình huống của MVCC (Multi Version Concurrency Control).

Ngoài ra, hầu hết các lệnh PostgreSQL có được các khóa của các chế độ thích hợp để đảm bảo rằng các bảng được tham chiếu không bị xóa hoặc sửa đổi theo cách không mong muốn trong khi các lệnh đang được thực thi. Ví dụ như lệnh TRUNCATE không thể thực hiện đồng thời với các lệnh thao tác khác trên cùng một bảng như SELECT..., để làm được điều TRUNCATE được cấp phát cho một khoá gọi là ACCESS EXCLUSIVE.

Các cấp khoá

Postgres có các cấp khoá sau đây:

  • Table-Level Locks
  • Row-Level Locks
  • Page-Level Locks
  • Advisory Locks

Các cấp khoá mô tả miền xung đột của các lệnh PostgreSQL ở các cấp độ bảng (table), dòng (row) hay là trang (page)...

Tuy nhiên trong bài viết này tôi xin phép trình bày hai cấp khoá là Table và Row. Bạn đọc có thể tìm hiểu thêm các loại khoá tại trang tài liệu của PostgreSQL.

Khoá cấp bảng (Table-Level Locks)

Là các khoá ở quy mô bảng, các khoá này được cấp phát tự động hoặc thông qua lệnh LOCK.

Tự động có nghĩa là phụ thuộc vào lệnh SQL nào khi gọi thì bạn ngay lập tức sẽ được cấp pháp khoá đó. Dưới đây là một số câu lệnh quen thuộc và các khoá được cấp tự động tương ứng khi bạn gọi chúng.

  • SELECT: ACCESS SHARE
  • UPDATE, DELETE, INSERT: ROW EXCLUSIVE
  • CREATE INDEX: SHARE
  • CREATE TRIGGER: SHARE ROW EXCLUSIVE
  • DROP TABLE, TRUNCATE: ACCESS EXCLUSIVE

Nhiều khoá và chi tiết hơn xem lại trang tài liệu của postgres.

Dưới đây là bảng thể hiện sự xung đột của các khoá với nhau.

table locking

Tôi có thể giải thích như sau: nhìn vào bảng chúng ta thấy khoá ACCESS SHARE sẽ xung đột với ACCESS EXCLUSIVE vì thế trong các transaction nếu lệnh nào đang được thực hiện trước (nắm khoá ACCESS SHARE) thì lệnh sau (nắm khoá ACCESS EXCLUSIVE) phải chờ cho đến khi transaction được hoàn thành mới có thể tiếp tục và ngược lại.

-- (1)
BEGIN; 
-- (2)
SELECT * FROM users; -- ACCESS SHARE LOCKS
-- (4)
COMMIT;
-- (3)
TRUNCATE users; -- ACCESS EXCLUSIVE LOCKS

Hãy thử chạy các lệnh trên trên hai tiến trình khác nhau theo các bước (1) (2) (3) (4) để xem điều gì xảy ra nhé.

Khoá cấp hàng (Row-Level Locks)

Các khoá cấp hàng được cấp phát bằng cách xác định tên của khoá trong câu truy vấn. Có 4 khoá là:

  • FOR UPDATE
  • FOR NO KEY UPDATE
  • FOR SHARE
  • FOR KEY SHARE

row locking

FOR UPDATE khiến các hàng được truy xuất bởi SELECT bị khóa như thể để cập nhật. Điều này giúp chúng không bị khóa, sửa đổi hoặc xóa bởi các transaction khác cho đến khi transaction hiện tại kết thúc. Nghĩa là, các transaction khác như DELETE hoặc UPDATE một trong số các hàng này sẽ bị chặn cho đến khi transaction hiện tại kết thúc.

Tương tự như Table-Level Locks, bảng trên mô tả xung đột giữa các khoá. Các khoá xung đột với nhau sẽ phải đợi cho đến khi khoá cấp phát trước được thực hiện xong thì mới đến lượt mình.

Ví dụ bạn phát triển một tính năng đổi quà, có một bảng quà chứa số lượng còn lại của quà muốn đổi và bảng lưu số điểm hợp lệ của bạn dùng để đổi quà. Khi đổi quà bạn cần lấy ra số lượng quà còn lại và số điểm của bạn, kiểm tra qua nhiều điều kiện khắc nghiệt và tốn rất nhiều thời gian nữa mới có thể đổi. Giả sử trong lúc yêu cầu thứ nhất đã lấy ra số lượng quà còn lại là 1 và có yêu cầu thứ hai ngay lập tức cũng lấy ra số lượng quà còn lại là 1 thì điều gì sẽ xảy ra nếu như cả hai tiếp tục đổi quà? Để ngăn chặn điều đó bạn có thể sử dụng Row-Level Locks, tức là khi một transaction đang lấy số lượng quà còn lại để bắt đầu validate thì transaction thứ hai cần chờ đợi cho đến khi transaction đầu kết thúc.

Deadlock

Deadlock xảy ra khi hai hoặc nhiều transaction giữ các khoá mà bên kia mong muốn. Ví dụ transaction thứ nhất có được khoá ACCESS EXCLUSIVE trên bảng A và sau đó muốn có tiếp khoá đó trên bảng B trong khi transaction thứ hai đã có khoá ACCESS EXCLUSIVE trên bảng B và bây giờ lại muốn có khoá đó trên bảng A thì lúc đó không có transaction nào có thể tiếp tục. PostgreSQL tự động phát hiện tình huống này và giải quyết bằng cách huỷ bỏ một trong các transaction có liên quan, transaction bị huỷ bỏ không thể đoán trước.

Deadlock cũng có thể xảy ra ở trong các khoá cấp hàng khi các transaction cũng giữ khoá của nhau.

Biện pháp bảo vệ tốt nhất chống lại các deadlock nói chung là tránh để cho các lệnh có được các khóa trên nhiều đối tượng (table/row) theo một thứ tự xác định.

Nếu transaction được thực hiện trên nhiều đối tượng liên quan, cách tốt nhất là làm sao cho thời gian thực hiện transaction càng ngắn càng tốt. Tránh giữ các transaction trong thời gian dài. Ví dụ cho một thực hành tồi là transaction sẽ được thực thi tiếp cho đến khi chờ đợi thông tin nhập của người dùng xong.

Tổng kết

Bài viết trên đây tôi đã trình bày về cách mà PostgreSQL sử dụng khoá để quản lý quyền truy cập đồng thời vào dữ liệu trong bảng. Mặc dù là dành riêng cho PostgreSQL nhưng tư tưởng sử dụng khoá vẫn tồn lại trong các loại cơ sở dữ liệu SQL khác như MySQL, SQL Server... Nắm được cách hoạt động của khoá sẽ giúp bạn ứng biến với những tình huống trong việc phát triển ứng dụng cùng SQL.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Trần Ngọc Hải2 năm trước
Bài viết quá hay quá chi tiết cảm ơn tác giả
Trả lời
Bấm hoặc cuộn mạnh để sang bài mới