Mục lục bài họcĐang ở d08-b2
Relational Databases, Normalisation and Transactions
Structure. A relational database stores data in tables; each row is a record describing one instance, and each column is a field. A primary key is the field or combination of fields that uniquely identifies each record. A foreign key is a field holding the primary key of another table, and it is what creates relationships. Referential integrity is the rule that a foreign key must refer to a record that actually exists, which prevents orphaned data such as an enrolment pointing to a deleted course.
Why normalise. Normalisation exists to remove the three anomalies caused by storing the same fact in more than one place. The update anomaly: changing a teacher's name requires editing many rows, and missing one leaves the database contradicting itself. The insertion anomaly: a new course cannot be recorded until a student enrols on it, because the row would have no key. The deletion anomaly: removing the last enrolment on a course destroys the record of the course itself. Learn the anomalies, not just the definitions of the normal forms — examiners ask for the anomalies.
The normal forms. First normal form requires atomic values with no repeating groups: a field must not hold a list. Second normal form additionally requires every non-key field to depend on the whole primary key, which matters only when the key is composite. Third normal form additionally removes transitive dependencies, where a non-key field depends on another non-key field rather than on the key. The working rule is that every field must depend on the key, the whole key, and nothing but the key.
The cost. Normalisation is not free. Data spread across several tables must be recombined with joins, so read-heavy systems perform more work per query. Some systems therefore deliberately keep controlled redundancy, trading consistency for speed; a data warehouse used for analysis is usually organised very differently from the transactional database it draws from. An index makes searching a column much faster but slows insertion and consumes storage, which is the same trade-off in miniature.
Transactions. A transaction is a group of operations that must all succeed or all fail — transferring money requires both the debit and the credit. Databases guarantee atomicity (all or nothing), consistency (rules such as referential integrity always hold), isolation (concurrent transactions do not see each other's partial work) and durability (a committed result survives a crash). Isolation is what prevents two simultaneous bookings of the same seat.
Cấu trúc. Cơ sở dữ liệu quan hệ lưu dữ liệu trong các bảng; mỗi hàng là một bản ghi mô tả một thể hiện, và mỗi cột là một trường. Khoá chính là trường hoặc tổ hợp trường xác định duy nhất mỗi bản ghi. Khoá ngoại là trường chứa khoá chính của một bảng khác, và chính nó tạo ra các mối quan hệ. Toàn vẹn tham chiếu là quy tắc rằng một khoá ngoại phải trỏ tới một bản ghi thực sự tồn tại, nhờ đó ngăn được dữ liệu mồ côi như một lượt đăng ký trỏ tới một môn học đã bị xoá.
Vì sao phải chuẩn hoá. Chuẩn hoá tồn tại để loại bỏ ba bất thường do việc lưu cùng một sự thật ở nhiều nơi. Bất thường khi sửa: đổi tên một giảng viên đòi sửa nhiều dòng, và sót một dòng là cơ sở dữ liệu tự mâu thuẫn với chính nó. Bất thường khi thêm: không ghi nhận được một môn học mới cho tới khi có sinh viên đăng ký, vì dòng đó sẽ thiếu khoá. Bất thường khi xoá: xoá lượt đăng ký cuối cùng của một môn sẽ xoá luôn thông tin về chính môn đó. Hãy học ba bất thường chứ đừng chỉ học định nghĩa các dạng chuẩn — đề thi hỏi các bất thường.
Các dạng chuẩn. Dạng chuẩn một đòi các giá trị phải nguyên tố và không có nhóm lặp: một trường không được chứa một danh sách. Dạng chuẩn hai đòi thêm rằng mọi trường không thuộc khoá phải phụ thuộc vào toàn bộ khoá chính, điều chỉ có ý nghĩa khi khoá là khoá tổ hợp. Dạng chuẩn ba đòi thêm việc loại bỏ phụ thuộc bắc cầu, tức khi một trường không thuộc khoá lại phụ thuộc vào một trường không thuộc khoá khác thay vì phụ thuộc vào khoá. Quy tắc thực dụng là mọi trường phải phụ thuộc vào khoá, vào toàn bộ khoá, và không vào gì ngoài khoá.
Cái giá. Chuẩn hoá không miễn phí. Dữ liệu trải ra nhiều bảng phải được ghép lại bằng phép nối, nên các hệ thống đọc nhiều phải làm nhiều việc hơn cho mỗi truy vấn. Vì vậy một số hệ thống cố ý giữ lại phần dư thừa có kiểm soát, đổi tính nhất quán lấy tốc độ; một kho dữ liệu dùng để phân tích thường được tổ chức khác hẳn cơ sở dữ liệu giao dịch mà nó lấy dữ liệu về. Chỉ mục làm việc tìm kiếm trên một cột nhanh hơn nhiều nhưng làm chậm việc chèn và tốn thêm dung lượng — đúng cùng một sự đánh đổi ở quy mô nhỏ hơn.
Giao dịch. Giao dịch là một nhóm thao tác phải cùng thành công hoặc cùng thất bại — chuyển tiền đòi cả thao tác trừ lẫn thao tác cộng. Cơ sở dữ liệu bảo đảm tính nguyên tử tức được tất cả hoặc không được gì, tính nhất quán tức các quy tắc như toàn vẹn tham chiếu luôn được giữ, tính cô lập tức các giao dịch chạy đồng thời không nhìn thấy phần việc dở dang của nhau, và tính bền vững tức kết quả đã xác nhận vẫn còn sau khi hệ thống gặp sự cố. Chính tính cô lập là thứ ngăn hai người cùng đặt một chỗ ngồi.
Một bảng duy nhất lưu: MaDon, NgayDat, MaKH, TenKH, DiaChiKH, MaSP, TenSP, DonGia, SoLuong. Một đơn hàng có thể gồm nhiều sản phẩm. Hãy chỉ ra ba bất thường, rồi tách bảng về dạng chuẩn ba và giải thích từng bước.
Ba bất thường. Khi sửa: khách hàng chuyển địa chỉ thì DiaChiKH phải sửa ở mọi dòng của mọi đơn hàng của khách đó; sót một dòng là hệ thống có hai địa chỉ mâu thuẫn cho cùng một người mà không biết cái nào đúng. Khi thêm: không thể ghi nhận một sản phẩm mới vào danh mục cho tới khi có ai đó đặt mua nó, vì dòng đó sẽ thiếu MaDon và MaKH. Khi xoá: xoá đơn hàng cuối cùng chứa một sản phẩm sẽ xoá luôn tên và đơn giá của sản phẩm đó khỏi hệ thống.
Bước 1 — dạng chuẩn một. Bảng đã ở dạng chuẩn một nếu mỗi ô chỉ chứa một giá trị. Nếu ban đầu người ta lưu nhiều sản phẩm của một đơn trong cùng một ô, phải tách thành nhiều dòng trước. Khoá chính lúc này là tổ hợp MaDon cộng MaSP, vì cần cả hai mới xác định duy nhất một dòng.
Bước 2 — dạng chuẩn hai: loại bỏ phụ thuộc vào MỘT PHẦN khoá. Xét từng trường không thuộc khoá. NgayDat, MaKH, TenKH và DiaChiKH chỉ phụ thuộc vào MaDon, tức chỉ phụ thuộc một phần của khoá tổ hợp. TenSP và DonGia chỉ phụ thuộc vào MaSP, cũng chỉ một phần. Chỉ SoLuong mới thực sự phụ thuộc vào cả hai. Vì vậy tách thành ba bảng: DonHang gồm MaDon là khoá chính, NgayDat, MaKH, TenKH, DiaChiKH; SanPham gồm MaSP là khoá chính, TenSP, DonGia; và ChiTietDon gồm MaDon và MaSP làm khoá chính tổ hợp cùng với SoLuong.
Bước 3 — dạng chuẩn ba: loại bỏ phụ thuộc bắc cầu. Trong bảng DonHang, TenKH và DiaChiKH không phụ thuộc vào MaDon một cách trực tiếp — chúng phụ thuộc vào MaKH, còn MaKH mới phụ thuộc vào MaDon. Đây chính là một phụ thuộc bắc cầu, và nó là lý do bất thường khi sửa vẫn còn tồn tại sau bước 2. Tách tiếp thành: DonHang gồm MaDon là khoá chính, NgayDat, MaKH là khoá ngoại; và KhachHang gồm MaKH là khoá chính, TenKH, DiaChiKH.
Kết quả cuối cùng — bốn bảng. KhachHang, DonHang, SanPham, ChiTietDon. Kiểm tra lại ba bất thường: đổi địa chỉ khách hàng nay chỉ sửa đúng một dòng trong bảng KhachHang; thêm một sản phẩm mới chỉ cần thêm một dòng vào SanPham mà không cần đơn hàng nào; và xoá một đơn hàng không động chạm gì tới bảng SanPham. Cả ba bất thường đã biến mất.
Cái giá phải nêu để lấy điểm đánh giá. Một báo cáo liệt kê tên khách hàng cùng tên sản phẩm nay phải nối bốn bảng thay vì đọc một bảng duy nhất, nên mỗi truy vấn tốn nhiều việc hơn. Với hệ thống đọc rất nhiều và ghi rất ít — chẳng hạn một kho dữ liệu phục vụ phân tích — người ta có thể cố ý giữ lại phần dư thừa để đổi tính nhất quán lấy tốc độ. Nhưng với cơ sở dữ liệu giao dịch, nơi dữ liệu thay đổi liên tục, chuẩn hoá gần như luôn là lựa chọn đúng.
Một hệ thống đặt vé máy bay ghi nhận một chỗ ngồi bằng hai thao tác: giảm số ghế trống đi một, và tạo một bản ghi đặt chỗ. Hãy giải thích điều gì xảy ra nếu hệ thống mất điện giữa hai thao tác, và điều gì xảy ra nếu hai người cùng đặt chỗ cuối cùng vào đúng một thời điểm.
Tình huống 1 — mất điện giữa hai thao tác. Nếu số ghế trống đã giảm nhưng bản ghi đặt chỗ chưa được tạo, hệ thống mất vĩnh viễn một ghế: nó không bán được cho ai vì bộ đếm nói đã hết, nhưng cũng không thuộc về ai vì không có bản ghi. Đây là trạng thái không nhất quán, và điều nguy hiểm là nó không tự lộ ra — không có thông báo lỗi nào, chỉ có một ghế biến mất.
Cách xử lý: tính nguyên tử. Hai thao tác phải được gói trong một giao dịch. Cơ sở dữ liệu ghi lại các thay đổi vào một nhật ký trước khi áp dụng, và chỉ khi cả hai thao tác hoàn tất mới xác nhận giao dịch. Nếu mất điện trước thời điểm xác nhận, khi khởi động lại hệ thống sẽ hoàn tác phần đã làm dở, đưa dữ liệu về đúng trạng thái trước khi bắt đầu. Nguyên tắc là được tất cả hoặc không được gì, không có trạng thái ở giữa.
Tình huống 2 — hai người cùng đặt chỗ cuối cùng. Không có cơ chế bảo vệ, chuỗi sự kiện có thể diễn ra như sau: giao dịch A đọc thấy còn 1 ghế; giao dịch B cũng đọc thấy còn 1 ghế vì A chưa ghi xong; A ghi số ghế còn lại là 0 và tạo bản ghi đặt chỗ; B cũng ghi số ghế còn lại là 0 và tạo bản ghi đặt chỗ. Kết quả là hai người cùng được xác nhận cho một ghế, và bộ đếm chỉ giảm một dù đã bán hai lần.
Cách xử lý: tính cô lập. Tính cô lập bảo đảm các giao dịch chạy đồng thời cho kết quả như thể chúng chạy lần lượt. Cơ chế thông dụng là khoá: giao dịch A khoá bản ghi số ghế trống cho tới khi nó xác nhận xong, nên B phải chờ; khi B được chạy tiếp, nó đọc thấy số ghế trống là 0 và bị từ chối. Một cơ chế thay thế là kiểm soát lạc quan: cả hai cùng chạy, nhưng khi xác nhận, hệ thống kiểm tra xem giá trị có bị thay đổi kể từ lúc đọc không, và nếu có thì huỷ giao dịch đó và yêu cầu thử lại.
Hai tính chất còn lại, nêu ngắn để đủ bộ. Tính nhất quán bảo đảm mọi ràng buộc như toàn vẹn tham chiếu vẫn đúng trước và sau giao dịch. Tính bền vững bảo đảm rằng một khi giao dịch đã được xác nhận và người dùng đã nhận thông báo thành công, kết quả không bị mất kể cả khi máy chủ tắt đột ngột ngay sau đó — điều này đạt được bằng cách ghi nhật ký xuống bộ nhớ bền trước khi báo thành công.
Cái giá cần nêu khi đánh giá. Khoá làm giảm mức song song: trong lúc A giữ khoá thì B phải chờ, nên thông lượng giảm khi có nhiều giao dịch cùng chạm vào một bản ghi. Vì vậy các hệ thống lớn thường cho phép chọn mức cô lập thấp hơn ở những nơi có thể chấp nhận rủi ro, đổi tính chính xác tuyệt đối lấy tốc độ.
Bẫy 2 — trình bày chuẩn hoá như thứ luôn luôn đúng. Cái giá là mỗi truy vấn phải nối nhiều bảng; hệ thống đọc rất nhiều có thể cố ý giữ dư thừa. Nêu được sự đánh đổi này là cách lấy điểm đánh giá.
Bẫy 3 — mô tả giao dịch chỉ bằng tính nguyên tử. Tính nguyên tử xử lý sự cố giữa chừng, nhưng chính TÍNH CÔ LẬP mới ngăn được hai người cùng đặt một chỗ ngồi. Hai vấn đề khác nhau và cần hai tính chất khác nhau.
Đọc xong rồi — làm thử ngay
Bài tập của chương Option: Object-Oriented Programming and Databases gồm 14 câu trắc nghiệm và 5 đề tự luận. Đáp án hiện ngay khi chọn, miễn phí.