Archive for July, 2009

Khoá – Locking

July 14, 2009

Đây em chọn “khoá” này cơ?

Đêm qua nhậu với ông bạn về, đang ngồi chơi với con bé con thì thấy NSND Thanh Hoa cứ ư ử “Đây em chọn lối này cơ” (Bài hát gì của anh An Thuyên, lại tranh thủ dìm hàng tý là mình chưa bao giờ thấy NSND này hát hay và xứng đáng với danh hiệu NSND), mình nghe thế đếch nào lại là “Đây em chọn khoá này cơ” (chắc do bia)? Lại chợt nhớ hôm T7 ngồi cafe với Minh Còi, Còi cũng nói về cái khoá (lock) này nên tranh thủ review phát. Chú ý: scope chỉ là database thôi nhé

Khoá là cơ chế giúp cho các truy nhập đồng thời đến cùng một shared resource và tất nhiên là trong môi trường đa người dùng. Chứ nếu chỉ là single user như kiểu MS Access thì khoá làm gì cho mất thời gian. Nói đến lock thì các bạn cũng phải biết những vấn đề liên quan như lost update, dead lock… Hiện tại có nhiều database, mỗi loại có những fundementals khác nhau (mình không nói loại nào hơn loại nào nhé) nên khi sử dụng cần phải biết những cơ bản về nó.

Dài dòng thế thôi chứ việc mà tất cả các developer phải làm là chọn một trong 2 chiến lược lock: optimistic và pessimistic (trong ngữ cảnh này dịch là bi quan và lạc quan nó không hợp lý lắm).

1. Pessimistic

Là chiến lược lock trước tài nguyên (rows) trước khi end users modify. (Cái này mà nói là bi quan thì e rằng hơi ….gì nhỉ?)

2. Optimistic

Là chiến lược chỉ lock tại thời điểm user modifying. Kể ra thì cũng hay nhưng vấn đề làm thế nào để biết mình đang sửa đổi bản ghi theo ý của mình. Chiến lược này nếu không khéo rất dễ bị hiện tượng lost update. Ví du bảng emp có trường name và date_of_birth. Cùng 1 lúc có 2 users A va B query dữ liệu record 5 trên application của mình. Sau đó A sửa trường name rồi commit. Tiếp theo B sửa trường date_of_birth rồi cũng commit. Một lát sau A query lại record 5 thấy vẫn là name cũ.

Vậy để tránh lost update thì làm thế nào. Có 2 cách:

–       Tạo thêm một column (kiểu integer hoặc date/timestamp) để lưu version của record. Việc maintain “version” column có thể thực hiện manually hoặc auto thông qua trigger.

–       Sử dụng checksum hoặc hash function để tính toán ra một giá trị dựa trên dữ liệu gốc. Có thể dùng checksum, hash hoặc MD5

Bản chất của cả 2 cách là một lần sửa đổi một record trên application đều phải check version hiện tại trong database có khớp với version mà mình đang query không. Nếu khớp thì việc sửa đổi được thực hiện, else thì end user phải check lại dữ liệu mình đang query rồi sẽ ra quyết định tiếp hay không. Ở cách 2 thì có vẻ sáng sủa hơn, không tốn bộ nhớ để lưu version column, hàm tính toán thì có thể không phụ thuộc vào database, tuy nhiên bù vào đó bạn phải tốn thêm một ít chi phí về mặt tốc độ để tính toán value của record.

Nói thêm một chút ở Oracle, phiên bản 10g trở đi có sử dụng trường ẩn ORA_ROWSCN based trên internal Oracle System Clock (SCN) tương tự như checksum nhưng không bị tốn thêm cost tính toán khi update. Để dùng được cái này thì table của bạn phải ở chế độ ROWDEPENDENCIES

3. Which is the best?

Pessimistic:  không phải check chiếc lằng nhằng làm gì, chỉ cần giữ lock trên bản ghi mà nó cần update là xong. Tuy nhiên nó chỉ useful trong môi trường stateful or connected environment, nôm na là luôn giữ kết nối đến database như kiểu client/server. Trong các application bây giờ số lượng end user càng lớn thì việc giữ connection quả là xa xỉ

Optimistic: Như đã nói ở trên (@Mr. Lê Dũng, Bộ Ngoại Giao), cách này phải luôn phải check version khi update. Tuy nhiên cách thức kiểm tra thì luôn luôn phức tạp và rất dễ quên. Sử dụng checksum không tốn bộ nhớ, lại có thể độc lập với database, nhưng lại tốn chi phí về tốc độ. Hơn nữa trong các table có chứa các trường LONG, RAW, LOB thì checksum chịu chết. Nếu trên database Oracle thì ORA_ROWSCN quả là có ưu thế, tuy nhiên chỉ apply cho 10g or higher

Vậy câu trả lời là: Tuỳ.

HN.

Advertisements