Đăng ký Đăng nhập
Trang chủ Nghiên cứu phương pháp xây dựng Storage Engine cho hệ quản trị cơ sở dữ liệu MyS...

Tài liệu Nghiên cứu phương pháp xây dựng Storage Engine cho hệ quản trị cơ sở dữ liệu MySQL

.PDF
75
134
149

Mô tả:

ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ NGUYỄN THỊ KHUÊ NGHIÊN CỨU PHƯƠNG PHÁP XÂY DỰNG STORAGE ENGINE CHO HỆ QUẢN TRỊ CƠ SỞ DỮ LIỆU MYSQL LUẬN VĂN THẠC SĨ CÔNG NGHỆ THÔNG TIN Hà Nội – 2012 ĐẠI HỌC QUỐC GIA HÀ NỘI TRƯỜNG ĐẠI HỌC CÔNG NGHỆ NGUYỄN THỊ KHUÊ NGHIÊN CỨU PHƯƠNG PHÁP XÂY DỰNG STORAGE ENGINE CHO HỆ QUẢN TRỊ CƠ SỞ DỮ LIỆU MYSQL Ngành: Công nghệ thông tin Chuyên ngành: Hệ thống thông tin Mã số: 60 48 05 LUẬN VĂN THẠC SĨ CÔNG NGHỆ THÔNG TIN NGƯỜI HƯỚNG DẪN KHOA HỌC: T.s Nguyễn Hải Châu Hà Nội – 2012 2 MỤC LỤC LỜI CAM ĐOAN ........................................................................................................1 MỤC LỤC...................................................................................................................2 DANH MỤC CÁC KÍ HIỆU VÀ CHỮ VIẾT TẮT .....................................................4 DANH MỤC CÁC BẢNG ..........................................................................................4 DANH MỤC CÁC HÌNH VẼ......................................................................................4 MỞ ĐẦU.....................................................................................................................5 CHƯƠNG 1. TỔNG QUAN VỀ MYSQL ...................................................................7 1.1. Hệ quản trị cơ sở dữ liệu MySQL ......................................................................7 1.2. Kiến trúc MySQL..............................................................................................9 1.3. Truy vấn dữ liệu trên MySQL .........................................................................11 1.3.1. Giao diện SQL ..........................................................................................11 1.3.2. Phân tách ..................................................................................................11 1.3.3. Tối ưu truy vấn .........................................................................................12 1.3.4. Thực thi truy vấn.......................................................................................13 1.3.5. Bộ đệm truy vấn........................................................................................13 1.3.6. Cache và Buffer ........................................................................................15 1.4. Các đặc trưng của MySQL ..............................................................................16 1.4.1. Quản lí kết nối và an ninh .........................................................................16 1.4.2. Quản lí đồng thời ......................................................................................17 1.4.3. Giao tác ....................................................................................................18 1.4.4. Điều khiển đồng thời đa phiên bản (MVCC) .............................................21 1.4.5. Chỉ mục ....................................................................................................22 CHƯƠNG 2. MYSQL PLUGGABLE STORAGE ENGINE ....................................25 2.1. Storage engine là gì? .......................................................................................25 2.2. Kiến trúc pluggable storage engine..................................................................27 2.3. Một số storage engine điển hình ......................................................................28 2.3.1. Một số storage engine có sẵn ....................................................................28 2.3.1.1. MyISAM ............................................................................................28 2.3.1.2. InnoDB ..............................................................................................31 2.3.1.3. Archive...............................................................................................36 2.3.1.4. Federated............................................................................................36 2.3.1.5. NDB Cluster.......................................................................................39 2.3.1.6. Memory..............................................................................................39 2.3.1.7. Merge.................................................................................................40 2.3.1.8. Blackhole ...........................................................................................42 2.3.1.9. CSV ...................................................................................................42 2.3.2. Lưu trữ theo cột và storage engine ............................................................43 2.3.2.1. Kĩ thuật lưu trữ theo cột......................................................................43 2.3.2.2. InfoBright...........................................................................................45 2.3.3. NoSQL và storage engine .........................................................................46 2.3.3.1. NoSQL là gì? .....................................................................................46 2.3.3.2. HandlerSocket ....................................................................................48 2.4. Sử dụng storage engine có sẵn.........................................................................49 2.4.1. Lựa chọn storage engine phù hợp..............................................................49 2.4.2. Một số thao tác cơ bản ..............................................................................50 3 CHƯƠNG 3. XÂY DỰNG STORAGE ENGINE......................................................53 3.1. Cơ sở hạ tầng của một storage engine..............................................................53 3.2. Mã nguồn của MySQL ....................................................................................54 3.3. Cấu trúc Handlerton ........................................................................................55 3.4. Lớp Handler ....................................................................................................58 3.5. Quá trình tạo một storage engine mới. .............................................................61 KẾT LUẬN ...............................................................................................................73 TÀI LIỆU THAM KHẢO..........................................................................................74 4 DANH MỤC CÁC KÍ HIỆU VÀ CHỮ VIẾT TẮT Từ viết tắt CSDL Hệ QTCSDL MVCC (Multiversion concurrence control) Mô tả Cơ sở dữ liệu Hệ quản trị cơ sở dữ liệu Điều khiển đồng thời đa phiên bản DANH MỤC CÁC BẢNG Tên bảng Bảng 2.1. Ma trận tương thích giữa các kiểu khóa trong InnoDB Bảng 2.2. Bảng so sánh tính năng giữa CSDL quan hệ và NoSQL Bảng 2.3. Bảng tổng kết một số đặc trưng của một số storage engine trong MySQL Trang 32 35 43 DANH MỤC CÁC HÌNH VẼ Hình 1.1. Hình 2.1. Hình 2.2. Hình 2.3. Hình 3.1. Hình vẽ Kiến trúc MySQL Server Kiến trúc bảng Federated Kiến trúc InfoBright Kiến trúc HandlerSocket Lớp dẫn xuất của pluggable storage engine Trang 10 37 45 48 59 5 MỞ ĐẦU Hiệu suất thực thi là một tiêu chí quan trọng đánh giá sự thành công của một hệ cơ sở dữ liệu. Đặc biệt trong thời đại bùng nổ thông tin hiện nay, khi mà khối lượng dữ liệu cực lớn và tăng nhanh chóng, không ngừng kéo theo những đòi hỏi cao về tốc độ cũng như tính hiệu quả của các hệ cơ sở dữ liệu. Tổ chức lưu trữ dữ liệu và triển khai cơ chế truy cập dữ liệu (hay còn gọi là thiết kế vật lí cơ sở dữ liệu) là một trong những giải pháp quan trọng, cơ bản được lựa chọn nhằm cải thiện đáng kể hiệu suất của hệ thống. Tổ chức lưu trữ và truy cập dữ liệu hợp lí và hiệu quả có thể đem lại những hiệu quả bất ngờ trong một số trường hợp. Thực tế chỉ ra rằng, mặc dù hiện nay có rất nhiều cách thức lưu trữ và tổ chức truy cập dữ liệu khác nhau, từ cách phân đoạn dữ liệu, tổ chức tệp trên các thiết bị, lưu đệm các dữ liệu có tần suất truy cập thường xuyên, hay các cơ chế lập chỉ mục để truy cập nhanh tới dữ liệu, … Tuy nhiên, mỗi cách thức có những ưu điểm và hạn chế riêng, có thể tốt trong trường hợp này nhưng lại không hiệu quả trong trường hợp khác. Hay nói một cách khác, không thể có cơ chế tốt nhất cho mọi trường hợp. Hơn nữa, mỗi hệ quản trị cơ sở dữ liệu hiện nay chỉ có thể triển khai một hoặc một vài cơ chế nhất định vì bản thân các cơ chế khác nhau có thể có những xung đột gây ảnh hưởng lẫn nhau. Và tất nhiên hệ quả là, mỗi hệ quản trị cơ sở dữ liệu thường chỉ đáp ứng tốt nhu cầu cho một hoặc một vài miền ứng dụng trong những trường hợp nhất định. Như vậy, có thể khẳng định rằng, không có cơ chế lưu trữ và truy cập tệp tốt cho mọi trường hợp cũng như không thể triển khai mọi cơ chế truy cập tệp trong một hệ quản trị cơ sở dữ liệu. Sẽ thật lí tưởng nếu có thể triển khai nhiều cơ chế tổ chức, truy cập tệp như là các gói giải pháp để đáp ứng nhu cầu của từng ứng dụng cụ thể và dễ dàng tra lắp cũng như gỡ bỏ ra khỏi hệ thống. Hệ quản trị cơ sở dữ liệu MySQL đã thực sự làm được điều này thông qua việc triển khai các storage engine, nơi chứa một tập các cơ chế lưu trữ, truy cập, hỗ trợ giao tác, các cơ chế khóa, cách ly, ... nhằm bổ sung các kiểu lưu trữ mới, dễ dàng tra lắp vào máy chủ thông qua cơ chế pluggable storage engine. Nó có thể là một storage engine đã được xây dựng sẵn hay bất kì một storage engine tự phát triển mới. Vì vậy, MySQL có thể đáp ứng được nhiều nhu cầu của nhiều ứng dụng trong nhiều hoàn cảnh khác nhau. Cơ chế pluggable storage engine đã tạo nên tính linh hoạt, mềm dẻo có lẽ duy nhất có của MySQL, góp phần không nhỏ vào sự thành công của MySQL với tư cách là một hệ quản trị cơ sở dữ liệu mã nguồn mở phổ biến nhất hiện nay. Đề tài “Nghiên cứu phương pháp xây dựng storage engine cho hệ quản trị cơ sở dữ liệu MySQL” hướng tới tìm hiểu kiến trúc pluggable storage engine của MySQL. Thông qua việc tìm hiểu một số storage engine điển hình và một số xu hướng lưu trữ dữ liệu nổi bật hiện nay cùng một số storage engine tiêu biểu của xu hướng đó (như 6 lưu trữ dữ liệu theo cột với InfoBright, NoSQL với HandlerSocket), luận văn đưa ra một cái nhìn tổng quan về MySQL storage engine cũng như một số gợi ý khi lựa chọn storage engine phù hợp cho một ứng dụng. Đồng thời, luận văn cũng hướng tới việc tìm hiểu những yếu tố cần cân nhắc khi xây dựng storage engine như lựa chọn cách tổ chức lưu trữ dữ liệu, cách thức lưu đệm, hỗ trợ chỉ mục, hỗ trợ giao tác, các yêu cầu đặc biệt,… và cuối cùng đi tới nghiên cứu một tiến trình xây dựng một storage engine mới được cho là khả thi. Nội dung chính của luận văn được chia thành 3 phần: Chương 1: Tổng quan về hệ quản trị CSDL MySQL. Chương này giới thiệu tổng quan về hệ quản trị cơ sở dữ liệu MySQL gồm: kiến trúc tổng quan của MySQL, những đặc điểm cơ bản của MySQL và đặc biệt nhấn mạnh những điểm khác biệt của MySQL so với các hệ QTCSDL khác như: sử dụng lớp pluggable storage engine cung cấp tính linh hoạt cho MySQL bằng khả năng lựa chọn cơ chế lưu trữ và truy cập phù hợp với từng ứng dụng; sử dụng các bộ đệm truy vấn và nhiều cơ chế lưu đệm khác nhau để cải thiện tốc độ truy vấn; triển khai các cơ chế chỉ mục, quản lí giao tác và lập chỉ mục tại các storage engine, … Chương 2: MySQL Pluggable storage engine. Trong chương này đi sâu nghiên cứu về một cơ chế đặc biệt có lẽ chỉ duy nhất có trong MySQL, pluggable storage engine. MySQL đưa ra một khái niệm mới đặc biệt, storage engine, nhằm xây dựng các cơ chế truy cập tệp phù hợp nhất với từng ứng dụng cụ thể. Phần này cũng tìm hiểu một số storage engine có sẵn và một số xu hướng phát triển của các cơ chế tổ chức, truy cập dữ liệu nổi bật hiện nay cùng một vài storage engine điển hình của các xu hướng đó. Từ đó, đưa ra một số gợi ý khi lựa chọn storage engine sử dụng cho ứng dụng của người dùng. Chương 3. Xây dựng storage engine. Nghiên cứu một quy trình xây dựng storage engine từ việc đưa ra các lựa chọn chức năng cần có của một storage engine, tìm hiểu cấu trúc handlerton và lớp handler trong MySQL đến tiến trình các giai đoạn thực hiện xây dựng một storage engine mới và cuối cùng là thử nghiệm chương trình thực nghiệm cho tiến trình đó. 7 CHƯƠNG 1. TỔNG QUAN VỀ MYSQL Sự phát triển mạnh mẽ của phong trào mã nguồn mở trong những năm gần đây đã thực sự đem lại cho nền công nghiệp phần mềm những triển vọng mới. Ngay từ khi được Richard Stallman khởi xướng (năm 1970) đến khi hệ điều hành Linux ra đời (năm 1991, do Linux Torvalds người Phần Lan viết nhân) và cho đến ngày nay, phần mềm mã nguồn mở dần khẳng định được vị thế của mình, với cộng đồng người phát triển lên tới hàng triệu người trên khắp thế giới, cùng sự phổ biến của một số phần mềm nguồn mở như Linux, Apache HTTP server, OpenSSL, MySQL, BIND, Sendmail,… hay những câu chuyện thành công của các công ty kinh doanh mã nguồn mở như MySQL AB, Red Hat, Slackware,… (điều mà những người chống phong trào mã nguồn mở cho là “không tưởng”). Trong phong trào đó, MySQL nổi lên như là một hệ quản trị cơ sở dữ liệu (hệ QTCSDL) phổ biến nhất hiện nay với khoảng 8 triệu bản cài đặt trên khắp thế giới. Vậy MySQL là gì? Cái gì khiến nó trở thành hệ QTCDL thành công đến như vậy? 1.1. Hệ quản trị cơ sở dữ liệu MySQL MySQL là hệ QTCSDL thuộc sở hữu của MySQL AB, AB là từ viết tắt của từ Thụy Điển “aktiebolag” nghĩa là công ty cổ phần hay công ty, được bắt đầu như một liên minh vốn đầu tư với mục tiêu xây dựng một hệ cơ sở dữ liệu quan hệ nguồn mở đáng tin cậy thay thế hệ cơ sở dữ liệu độc quyền thương mại. MySQL AB tạo ra doanh thu bằng cách bán giấy phép thương mại, hỗ trợ và cung cấp các dịch vụ phát triển chuyên nghiệp gồm tư vấn, đào tạo, chứng nhận sản phẩm. MySQL là hệ QTCSDL quan hệ hỗ trợ đầy đủ các câu lệnh SQL. Nó cho phép phát triển trên nhiều nền tảng phần cứng khác nhau. Hơn nữa, MySQL được phát triển dựa trên ngôn ngữ C/C++, ngôn ngữ sử dụng để xây dựng gần như toàn bộ hệ điều hành Linux cũng như Microsoft Windows và Macintosh. Nó được thiết kế dựa trên kiến trúc client/server. MySQL được đánh giá là một hệ QTCSDL phát triển khá đầy đủ và có độ tin cậy, tính ổn định, hiệu suất cao cũng như dễ sử dụng. Đặc biệt, MySQL cung cấp một cơ chế tuyệt vời cho phép tổ chức lưu trữ dữ liệu theo nhiều cách khác nhau để đạt hiệu quả cao nhất phù hợp với từng hoàn cảnh cụ thể gọi là pluggable storage engine. Điều đó khiến cho MySQL được đánh giá là có tính linh hoạt rất cao. Tại tầng thấp nhất của hệ thống, các máy chủ được xây dựng dựa trên mô hình đa luồng. Về mặt chức năng, nhiều phần trong lõi của MySQL được xây dựng từ những năm 1980. Đến năm 1995, ngôn ngữ truy vấn dữ liệu SQL được đưa vào hệ thống. MySQL sử dụng trình biên dịch GNU C (GCC) có khả năng cung cấp tính mềm dẻo tuyệt vời cho mọi môi trường đích. 8 Các công cụ máy khách của MySQL phần lớn được viết bằng ngôn ngữ C nên có tính di động và tốc độ cao hơn. Các thư viện máy khách, các cơ chế truy cập có thể được viết bằng bất kì ngôn ngữ lập trình nào như .Net, Java, ODBC,… MySQL sử dụng chiến lược phát triển song song để đảm bảo vẫn duy trì các phiên bản cũ trong khi phát triển các phiên bản mới. Việc này tạo nên sự khác biệt cơ bản so với các phần mềm bản quyền thương mại, nơi mà ngay khi các nhà cung cấp đưa ra phiên bản mới thì các phiên bản cũ bị dừng lại. Điều đó buộc các khách hàng phải thay đổi môi trường cùng với các nỗ lực phát triển kèm theo, đặc biệt khi có những thay đổi về mặt kiến trúc. Trong khi đó, MySQL cùng với chiến lược đa bản phát hành cho phép người dùng duy trì các sản phẩm lâu dài hơn mà vẫn đảm bảo được hỗ trợ. Do đó, khách hàng có nhiều thời gian chuẩn bị trước những bước thay đổi cần thiết đồng thời có thể đảm bảo sử dụng tài nguyên hiệu quả nhất mà không phải vội vã thay đổi kế hoạch dài hạn. Sự phát triển của MySQL cũng như các phần mềm nguồn mở khác tuân theo tiến trình gồm nhiều giai đoạn. Mỗi giai đoạn có thể có nhiều bản phân phối khác nhau. Các giai đoạn phát triển như sau: Giai đoạn 1: Giai đoạn phát triển (Development) – đây là giai đoạn mà các tập tính năng hoặc sản phẩm mới được lập kế hoạch hoặc triển khai như một hướng phát triển mới. Giai đoạn 2: Alpha – là giai đoạn triển khai sàng lọc tính năng và chỉnh sửa khiếm khuyết (sửa lỗi). Giai đoạn 3: Beta – các tính năng được “đóng băng” (không thể thêm các tính năng mới), bổ sung các kiểm thử chuyên sâu và triển khai dò tìm khiếm khuyết. Giai đoạn 4: Gamma – Về cơ bản, các sản phẩm trong giai đoạn này là mã đã được đóng băng và các vòng kiểm thử cuối cùng đã được tiến hành. Các sản phẩm trong giai đoạn này thường là các ứng viên sẽ đưa ra phát hành. Giai đoạn 5: Stable – Nếu không tìm thấy khiếm khuyết nghiêm trọng, mã được công bố là ổn định và sẵn sàng để phân phối sản phẩm. Khi sử dụng MySQL, tùy vào mục đích sử dụng của người dùng mà có thể lựa chọn các bản phân phối phù hợp. Tuy nhiên, nên sử dụng phiên bản alpha mới nhất cho những phát triển mới. Điều đó tạo ra cơ hội tốt hơn khi bản chỉnh sửa đã được kiểm thử trước tại giai đoạn alpha. MySQL là một hệ QTCSDL mã nguồn mở tuân thủ theo giấy phép nguồn mở GPL (General Public License). MySQL AB sử dụng giấy phép nguồn mở GPL như là điểm chính trong mô hình kinh doanh. MySQL AB thừa nhận cộng đồng mã nguồn mở GNU cũng như các liên danh đầu tư với MySQL AB đều được kí kết dưới cùng một triết lí và giấy phép. 9 Đặc biệt, MySQL sử dụng khái niệm cấp phép kép (dual – license). Có nghĩa là, bên cạnh các sản phẩm tuân thủ đúng giấy phép nguồn mở GPL, MySQL cũng được cấp phép như một sản phẩm thương mại. Một giấy phép thương mại cho phép MySQL sở hữu mã nguồn, cũng như bản quyền về tên, logo, và các tài liệu liên quan. Đây là điểm độc đáo khác hẳn với các công ty mã nguồn mở khác. MySQL AB giữ lại các tài sản trí tuệ của phần mềm trong khi vẫn tận dụng sự hỗ trợ của cộng đồng những người phát triển trên toàn cầu để mở rộng và phát triển phần mềm. Điều này đã khiến cho MySQL nhanh chóng trở thành một hệ QTCSDL mã nguồn mở ổn định, có tính linh hoạt và phổ biến nhất hiện nay. Vấn đề đặt ra là, khi MySQL vừa được cấp phép như phần mềm nguồn mở vừa được coi là phần mềm thương mại thì liệu có thực sự được phép chỉnh sửa hay không? Câu trả lời là có. Bất kì người phát triển nào đều có thể chỉnh sửa MySQL, tất nhiên phải tuân thủ giấy phép nguồn mở GPL. Đồng thời cũng có thể chỉnh sửa dưới giấy phép thương mại trong trường hợp muốn sử dụng bản chỉnh sửa cho những phát triển riêng hoặc gói hay nhúng MySQL vào trong sản phẩm thương mại đã có. 1.2. Kiến trúc MySQL So với rất nhiều hệ CSDL khác, MySQL có rất nhiều khác biệt. Mặc dù MySQL không hoàn hảo nhưng nó lại được đánh giá là một hệ QTCSDL linh hoạt có khả năng làm việc tốt trong nhiều môi trường khác nhau đáp ứng nhiều mục đích đa dạng, đặc biệt là trong các ứng dụng web. Hiện nay, MySQL có khả năng triển khai trong các ứng dụng nhúng, kho dữ liệu, lập chỉ mục nội dung và các phần mềm phân phối, các hệ thống đòi hỏi tính sẵn sàng cao, các xử lí giao tác trực tuyến (OLTP), … MySQL vô cùng linh hoạt theo nhiều cách khác nhau. Nó có thể được cấu hình để chạy tốt trên nhiều nền tảng phần cứng và hỗ trợ cho nhiều kiểu dữ liệu khác nhau thông qua một cơ chế độc đáo chỉ có duy nhất trên MySQL, pluggable storage engine. Các storage engine được thiết kế độc lập với xử lí truy vấn và các nhiệm vụ khác trong máy chủ như một trình runtime plugin. Tùy vào ứng dụng cụ thể, có thể lựa chọn cách thức lưu trữ dữ liệu, cách thể hiện và các đặc trưng tối ưu nhất thông qua việc lựa chọn các storage engine đã có phù hợp, hay tự xây dựng storage engine riêng. Kiến trúc hệ thống MySQL được mô tả như là một hệ thống phân lớp các hệ thống con. Trong khi mã nguồn chưa được biên dịch thành các phần hoặc mô-đun riêng, mã nguồn của các hệ thống con được tổ chức dưới dạng cây phân cấp. Hệ thống được phát triển dựa trên các thư viện cơ sở cung cấp các chức năng mức thấp như điều khiển luồng, tổ chức lưu trữ trong bộ nhớ, các thao tác mạng, đăng nhập, và thậm chí cả điều khiển truy cập và các thao tác quản lí. Các thư viện này được kết hợp với nhau tạo thành các hệ thống con và các hệ thống con có thể được xây dựng dựa trên các hệ thống con khác. Các hệ thống giao tiếp thông qua một giao diện API chuẩn. Giao diện API này cho phép hệ thống MySQL vừa được sử dụng như một máy chủ độc lập, vừa 10 như một hệ CSDL nhúng trong một ứng dụng lớn hơn. Kiến trúc của MySQL được mô tả chi tiết như hình 1.1 sau: Hình 1.1. Kiến trúc của MySQL server, trong [4, pp.1185] Lớp trên cùng là các lớp kết nối cơ sở dữ liệu (Connector): cung cấp phương thức truy cập cho các ứng dụng máy khách. Các ứng dụng này có thể được viết bằng bất kì ngôn ngữ nào như C, .Net, PHP, ODBC, …. Các công cụ phụ trợ được nhóm trong nhóm các tiện ích và dịch vụ quản lí gồm sao lưu và khôi phục dữ liệu, an ninh, nhân bản, phân cụm, quản trị, cấu hình, … Lớp nằm ngay dưới lớp kết nối là lớp connection pool. Đây là lớp quản lí tất cả các truy cập của người dùng như xác thực người dùng, xử lí luồng, bộ nhớ, bộ đệm tiến trình cần thiết cho một kết nối của máy khách. Lớp kế tiếp là lớp quan trọng nhất của một hệ thống CSDL, nơi xử lí các truy vấn người dùng. Tại lớp này, các truy vấn được đưa vào thông qua giao diện SQL, sau đó được phân tách, tối ưu, thực thi và lưu đệm. Sự độc đáo của MySQL được thể hiện trong lớp plugable storage engine. Lớp này tạo nên sự linh hoạt cho hệ thống thông qua việc xây dựng các cách thức quản lí dữ liệu hoặc lưu trữ tệp hoặc các cơ chế truy cập đa dạng khác nhau. Tính mềm dẻo này là duy nhất có ở MySQL. Storage engine cung cấp khả năng điều chỉnh CSDL bằng cách cung cấp một vài cơ chế lưu trữ dữ liệu. Máy chủ kết nối với các storage engine thông qua một giao diện storage engine chuẩn. Giao diện này che giấu sự khác nhau giữa các storage engine và khiến chúng trong suốt tại tầng truy vấn. Giao diện API chứa các chức năng mức thấp thực hiện các quá trình như là bắt đầu giao tác hoặc thêm dữ liệu 11 vào một hàng với khóa chính đã biết, … Các storage engine không phân tách SQL hoặc kết nối với các storage engine khác; chúng chỉ trả lời yêu cầu từ một máy chủ. Tầng thấp nhất của hệ thống là lớp truy cập tệp. Tầng này chứa các cơ chế lưu trữ, đọc và ghi dữ liệu, hệ thống đọc và ghi các thông tin biên bản và sự kiện. Đây cũng là lớp gần nhất với hệ điều hành cùng với các điều khiển luồng, tiến trình và bộ nhớ. 1.3. Truy vấn dữ liệu trên MySQL MySQL là một hệ QTCSDL quan hệ. Các yêu cầu người dùng được đưa vào thông qua giao diện SQL, sau đó được phân tách, tối ưu, thực thi và cuối cùng, kết quả được gửi lại cho người dùng thông qua giao diện SQL. 1.3.1. Giao diện SQL Giao diện SQL cung cấp các cơ chế để nhận các câu lệnh và chuyển kết quả tới người dùng. Giao diện SQL của MySQL được xây dựng trên chuẩn ANSI (American National Standards Institute) và chấp nhận mọi câu lệnh SQL cơ bản như mọi máy chủ CSDL theo chuẩn ANSI khác. Mặc dù rất nhiều câu lệnh trong MySQL có các lựa chọn không theo chuẩn ANSI nhưng những người phát triển vẫn tìm thấy điểm tương đồng với chuẩn này. Khi nhận được một yêu cầu kết nối tới máy chủ CSDL từ đường truyền mạng, một luồng (thread) được tạo ra cho mỗi kết nối. Tiến trình xử lí luồng là phần quan trọng nhất trong máy chủ MySQL. MySQL được xây dựng như một ứng dụng đa luồng thực sự nơi mà mỗi luồng được thực thi độc lập so với các luồng khác. Các câu lệnh SQL được lưu trữ theo một cấu trúc phân lớp và các kết quả được gửi tới người dùng bằng cách ghi các kết quả đó ra các phương thức truyền thông mạng. 1.3.2. Phân tách Khi một máy khách gửi tới một truy vấn, một luồng mới được tạo ra. Câu lệnh SQL được chuyển tới bộ phân tách để xác nhận cú pháp (hoặc từ chối nếu có lỗi). Bộ phân tách của MySQL sử dụng kịch bản Lex-YACC được biên dịch bằng Bison. Bộ phân tách sẽ xây dựng một cấu trúc truy vấn để thể hiện câu truy vấn viết bằng ngôn ngữ SQL trên bộ nhớ trong như là một cấu trúc cây (hay còn gọi là cây cú pháp trừu tượng). Sau đó sử dụng cấu trúc đó để thực thi truy vấn. Bộ phân tách sẽ đọc câu lệnh SQL, sau đó tách câu lệnh thành các phần và gán các tham số, các lựa chọn, các đoạn lệnh cho một cấu trúc các biến và danh sách. Cấu trúc này sẽ được sử dụng cho mọi bước tiếp theo của tiến trình truy vấn. Cấu trúc Lex chứa một danh sách các bảng được sử dụng, các tên trường tham chiếu đến, các điều kiện, các biểu thức và tất cả các phần của câu truy vấn đó trên những không gian lưu trữ phân biệt. 12 Bộ phân tách đọc các câu lệnh SQL và so sánh các biểu thức (gồm các token và các kí hiệu) với các luật định nghĩa trong mã nguồn. Các luật này được xây dựng trong mã nguồn sử dụng Lex và YACC và sau đó được biên dịch bằng Bison để phù hợp với bộ phân tích từ vựng. Ngay khi bộ phân tách xác thực một biểu thức và tách câu truy vấn thành các phần, nó gán kiểu câu lệnh thích hợp cho cấu trúc luồng đó và trả điều khiển cho bộ xử lí câu lệnh. Bộ xử lí câu lệnh giống như bộ chuyển đổi câu lệnh. Bộ phân tách truy vấn chỉ kiểm tra tính đúng đắn của các câu lệnh SQL chứ không xác minh sự tồn tại của các bảng hoặc các thuộc tính được tham chiếu cũng như không kiểm tra các lỗi ngữ nghĩa như là sử dụng một hàm hợp mà không sử dụng mệnh đề GROUP BY. Thay vào đó, việc xác thực được đưa tới quá trình tối ưu hóa. Do đó, cấu trúc truy vấn từ bộ phân tách được đưa tới bộ xử lí truy vấn và điều khiển được chuyển tới bộ tối ưu truy vấn. 1.3.3. Tối ưu truy vấn MySQL sử dụng chiến lược SELECT – PROJECT – JOIN để cố gắng xây dựng lại truy vấn. Đầu tiên, sử dụng câu lệnh SELECT để hạn chế số lượng các tuples, sau đó thực hiện phép chiếu để để giảm số lượng các thuộc tính (trường) trên các tuples kết quả và cuối cùng thực hiện lệnh hợp theo điều kiện. Bước đầu tiên của quá trình tối ưu hóa là kiểm tra sự tồn tại của bảng và quyền truy cập của người dùng. Nếu có lỗi thì một thông báo lỗi được đưa ra và điều khiển được trả về cho trình quản lí luồng. Ngay khi các bảng được xác thực, chúng sẽ được mở và các khóa thích hợp sẽ được sử dụng để điều khiển đồng thời. Ngay khi các công việc cài đặt và bảo trì được hoàn thành, trình tối ưu sử dụng cấu trúc truy vấn bên trong được phân tích bởi Lex và đánh giá điều kiện WHERE của truy vấn đó. Các kết quả trả về như là các bảng tạm thời để chuẩn bị cho bước tiếp theo. Nếu có xuất hiện phép toán UNION, trình tối ưu thực thi các đoạn SELECT của tất cả các câu lệnh trong vòng lặp trước khi tiếp tục. Bước tiếp theo của quá trình tối ưu hóa là thực thi phép chiếu. Chúng được thực hiện theo cách thức tương tự như các đoạn giới hạn, lặp lại lưu trữ các kết quả tức thời như các bảng tạm thời và chỉ lưu lại các thuộc tính được chỉ định trong các cột được chỉ định trong câu lệnh SELECT. Sau đó, cấu trúc được phân tích cho bất kì điều kiện JOIN nào được xây dựng sử dụng lớp join và gọi tới phương thức join::optimize(). Tại bước này, truy vấn được tối ưu hóa thông qua việc đánh giá biểu thức và loại bỏ các điều kiện mà kết quả trong các nhánh chết hoặc các điều kiện luôn đúng hoặc luôn sai. Trình tối ưu cố gắng loại bỏ các điều kiện tri thức tồi (known – bad) trong câu truy vấn trước khi thực thi lệnh join bởi vì lệnh join tốn nhiều chi phí cũng như thời gian nhất trong tất cả các phép toán quan hệ. Cũng lưu ý rằng, bước tối ưu phép toán join được thực hiện cho mọi câu lệnh có mệnh đề WHERE hoặc HAVING bất kể nó có điều 13 kiện join hay không. Ngay khi tối ưu câu lệnh join được hoàn thành, trình tối ưu sử dụng một danh sách các câu lệnh điều kiện để định tuyến truy vấn tới một phương thức thư viện thích hợp để thực thi. 1.3.4. Thực thi truy vấn Gồm một tập các phương thức thư viện được thiết kế để triển khai các truy vấn cụ thể. Ví dụ, phương thức mysql_insert() được thiết kế để chèn dữ liệu, phương thức mysql_select() được thiết kế để tìm và trả ra dữ liệu thỏa mãn mệnh đề WHERE. Thư viện các phương thức này được lưu trữ trong rất nhiều tệp mã nguồn dưới cùng một tên tệp (ví dụ như sql_insert.cc hoặc sql_select.cc). Tất cả các phương thức đó đều có một tham số như một đối tượng luồng cho phép phương thức đó truy cập vào cấu trúc truy vấn bên trong và dễ dàng thực thi. Kết quả thực thi của mỗi phương thức được trả về sử dụng thư viện đường truyền thông mạng. 1.3.5. Bộ đệm truy vấn Rất nhiều hệ QTCSDL lưu lại các kế hoạch thực thi truy vấn (plan), do đó máy chủ có thể bỏ qua các bước phân tách và tối ưu hóa cho các truy vấn lặp lại. MySQL không những làm được điều đó mà còn cho phép lưu đệm tập các kết quả truy vấn cho các câu lệnh SELECT. Đây có thể coi là kĩ thuật duy nhất có trong MySQL. Bộ nhớ đệm truy vấn giữ lại chính xác các bit của kết quả truy vấn trả về cho người dùng. Khi có một truy vấn đã được thực hiện trước đó rồi (xảy ra cache hit), thay vì phân tách, tối ưu và thực thi câu truy vấn, máy chủ chỉ đơn giản trả ra các kết quả đã được lưu trữ trước đó ngay lập tức. Điều này làm tăng hiệu suất xử lí truy vấn. Bộ nhớ đệm truy vấn sẽ lưu vết tới các bảng mà câu truy vấn đó dùng, và nếu một trong các bảng đó thay đổi, nó sẽ làm mất hiệu lực truy cập vào bộ đệm cache. Chính sách làm mất hiệu lực thô này dường như không hiệu quả khi những thay đổi trên bảng có thể không ảnh hưởng tới các kết quả lưu trữ trong bộ đệm nhưng đó là hướng tiếp cận đơn giản với chi phí thấp, điều này rất quan trọng với các hệ thống thường xuyên bận. Bộ đệm truy vấn được thiết kế hoàn toàn trong suốt đối với các ứng dụng. Các ứng dụng không cần biết dữ liệu được MySQL trả ra là từ trong bộ đệm hay do quá trình thực hiện truy vấn trên thực tế. Các kết quả này là như nhau hay nói cách khác, bộ đệm truy vấn thường không làm thay đổi ngữ nghĩa. MySQL làm thế nào để kiểm tra một câu lệnh đã được thực thi trước đó hay chưa? Cách thức mà MySQL sử dụng ở đây vô cùng đơn giản và khá nhanh: bộ đệm là một bảng tìm kiếm. Khóa tìm kiếm là một giá trị băm của câu truy vấn đó, CSDL đang sử dụng, phiên bản giao thức của máy khách và một giá trị hữu dụng có thể làm ảnh hưởng tới các giá trị byte thực tế trong kết quả truy vấn. 14 MySQL không phân tích cú pháp, “bình thường hóa” hoặc tham số hóa một câu lệnh khi kiểm tra câu lệnh đã được thực thi hay chưa. Nó sử dụng chính xác câu lệnh và các bit dữ liệu khác mà người dùng gửi tới. Bất kì sự khác biệt nào như là trong các kí tự, khoảng trống hoặc chú thích đều có thể khiến câu truy vấn đó không tương thích với câu truy vấn đã được lưu đệm trước đó. Vì thế nên cẩn thận khi viết câu truy vấn. Sử dụng các kiểu và định dạng nhất quán là một thói quen tốt nhưng trong trường hợp này nó còn có thể giúp hệ thống nhanh hơn. Kết quả truy vấn sẽ không được lưu đệm nếu như câu truy vấn sinh ra nó không xác định. Vì thế bất kì câu lệnh nào chứa các hàm không xác định như NOW(), CURRENT_DATE(), CURRENT_USER() hoặc CONNECTION_ID() đều sẽ không được lưu đệm. Trong thực tế, bộ đệm truy vấn không làm việc với truy vấn yêu cầu các hàm do người dùng định nghĩa, các hàm lưu trữ, các biến người dùng, các bảng tạm thời, các bảng trong CSDL mysql, hoặc bất kì bảng nào chứa một độc quyền mức dòng. Vậy MySQL có thực sự không kiểm tra bộ đệm nếu truy vấn chứa một hàm không xác định không? Thực ra không đúng như vậy, MySQL không thể biết một câu truy vấn có chứa một hàm không xác định trừ khi nó phân tách câu truy vấn đó, và việc tìm kiếm bộ đệm diễn ra trước khi thực hiện phân tách câu truy vấn. Máy chủ lúc này chỉ kiểm tra xem câu truy vấn đó có bắt đầu bằng các kí tự SEL hay không. Bộ đệm truy vấn của MySQL có thể cải thiện hiệu suất nhưng nó cũng có một vài vấn đề cần lưu ý khi sử dụng. Khi sử dụng bộ đệm truy vấn sẽ làm tăng thêm chi phí khi đọc và ghi dữ liệu:  Các truy vấn đọc dữ liệu phải kiểm tra bộ đệm trước khi bắt đầu.  Nếu truy vấn đó được lưu đệm và chưa nằm trong bộ đệm, cần phải mất phí để lưu trữ kết quả sau khi sinh nó.  Việc ghi dữ liệu cho các câu lệnh cũng mất chi phí. Khi ghi dữ liệu phải làm mất hiệu lực truy cập vào bảng đang thay đổi của tất cả các truy vấn khác. Tuy nhiên, chi phí này không lớn lắm do đó bộ đệm truy vấn vẫn đạt được hiệu quả khả thi. Nhưng vẫn còn một số vấn đề khác làm tăng thêm chi phí. Đối với những người sử dụng InnoDB, các giao tác có thể hạn chế tính hữu ích của bộ đệm truy vấn. Khi một câu lệnh bên trong một giao tác chỉnh sửa một bảng, máy chủ sẽ làm mất hiệu lực của bất kì câu truy vấn đã được lưu đệm tham chiếu tới bảng đó, ngay cả khi tính đa phiên bản của InnoDB có thể che giấu những thay đổi của giao tác với các câu lệnh khác, bảng đó cũng không thể lưu đệm toàn cục cho đến khi giao tác được commit. Do đó, không có câu truy vấn nào trên bảng (cả bên ngoài và bên trong giao tác) có thể được lưu trữ cho đến khi giao tác được commit. Như vậy, một giao tác có thời gian thực thi lâu sẽ làm tăng số lượng các bộ đệm truy vấn bị nhỡ. Việc làm mất hiệu lực cũng trở thành một vấn đề khi bộ đệm truy vấn lớn. Nếu có quá nhiều truy vấn trên bộ đệm, việc làm mất hiệu lực có thể mất nhiều thời gian và 15 khiến cho toàn bộ hệ thống ngưng lại trong khi nó vẫn đang làm việc. Điều đó xảy ra do có một khóa toàn cục trên bộ đệm truy vấn sẽ chặn tất cả các truy vấn cần tham chiếu đến nó. Quá trình truy cập diễn ra cả khi kiểm tra truy vấn đã được thực hiện trước đó hay chưa và khi kiểm tra có bất kì truy vấn không hợp lệ. 1.3.6. Cache và Buffer Cache và Buffer đảm bảo dữ liệu có tần suất sử dụng thường xuyên nhất phải sẵn sàng theo cách thức hiệu quả nhất có thể. Nói cách khác, dữ liệu phải thường trú và sẵn sàng được đọc tại mọi thời điểm. Cache làm giảm thời gian phản hồi cho các yêu cầu dữ liệu bởi vì dữ liệu nằm ngay trong bộ nhớ trong mà không cần thiết phải truy tìm dữ liệu trên đĩa. Hệ thống Cache được tạo ra để đóng gói tất cả các thao tác lưu đệm trong tập các hàm chuẩn. Bộ nhớ đệm thường được triển khai trong các phần khác nhau của mã nguồn để phù hợp với kiểu dữ liệu được lưu đệm. Các loại bộ đệm bao gồm: Bộ đệm bảng: tối thiểu chi phí mở, đọc và đóng bảng (tệp .frm trên đĩa). Bộ đệm bảng được thiết kế để lưu trữ các metadata của bảng trong bộ nhớ trong. Điều đó khiến cho một luồng (thread) đọc lược đồ của một bảng nhanh hơn mà không cần phải mở lại tệp đó mỗi khi truy cập đến. Mỗi một luồng có danh sách các cấu trúc bộ đệm bảng của riêng nó. Nó cho phép các luồng duy trì khung nhìn riêng của các bảng để nếu một luồng đang thay đổi một lược đồ bảng (nhưng chưa commit) thì các luồng khác có thể sử dụng bảng đó với lược đồ ban đầu. Cấu trúc này được lưu như một danh sách kết nối trong bộ nhớ trong và tương thích với mỗi luồng. Bộ đệm bản ghi: nâng cao khả năng đọc dữ liệu tuần tự từ các storage engine. Bộ đệm bản ghi thường chỉ được sử dụng trong khi duyệt bảng. Nó hoạt động giống như một bộ đệm đọc trước (read-ahead buffer) bằng cách tìm kiếm trên một khối (block) dữ liệu, nên làm giảm việc truy cập đĩa trong quá trình duyệt. Như vậy hiệu suất sẽ được cải thiện. Bộ đệm bản ghi cũng được sử dụng trong quá trình ghi dữ liệu một cách tuần tự bằng cách trước tiên ghi dữ liệu mới (hoặc sửa đổi) vào bộ nhớ đệm, sau đó ghi dữ liệu từ bộ đệm vào đĩa khi đầy. Bằng cách đó, hiệu suất ghi sẽ được cải thiện. Bộ đệm khóa: là bộ đệm được sử dụng cho các dữ liệu chỉ mục thường xuyên. Bộ đệm khóa được truy cập trong mọi thao tác đọc chỉ mục. Nếu một chỉ mục được tìm thấy trong bộ đệm thì nó sẽ được đọc từ đó; ngược lại, một khối chỉ mục mới phải được đọc từ đĩa và đặt vào bộ đệm. Kích thước bộ đệm có giới hạn cho nên không phải mọi khối của tệp chỉ mục được lưu trữ trong bộ nhớ trong. Làm thế nào để hệ thống biết được khối nào vừa mới được sử dụng? Giải pháp đưa ra là sử dụng một hệ giám sát để kiểm soát tần suất sử dụng của các khối chỉ mục bằng cách lưu lại giá trị warm. Warm nhận các giá trị: lạnh (BLOCK_COLD), ấm (BLOCK_WARM), và nóng (BLOCK_HOT). Khi các khối nguội và các khối mới trở nên ấm, các khối lạnh bị 16 thanh lọc, các khối ấm được bổ sung vào. Nó sử dụng chiến lược thay thế trang, bộ đệm khóa sẽ lưu vết các khối chỉ mục bị thay đổi (gọi là bị vấy bẩn – dirty). Khi một khối bị thay đổi (dirty) được thanh lọc, dữ liệu của nó được ghi trở lại tệp chỉ mục trước khi bị thay thế. Ngược lại, khi một khối sạch (clean) được thanh lọc, nó đơn giản chỉ bị xóa ra khỏi bộ nhớ trong. Bộ đệm quyền truy cập: được sử dụng để lưu trữ các dữ liệu cấp quyền trên một tài khoản người dùng. Dữ liệu này được lưu trữ theo cùng một cách với danh sách điều khiển truy cập, nơi lập danh sách toàn bộ quyền của một người dùng đối với một đối tượng trong hệ thống. Bộ đệm quyền sử dụng bảng băm FILO (vào trước, ra sau). Dữ liệu của bộ đệm được thu thập khi đọc các bảng phân quyền trong quá trình khởi tạo và xác thực người dùng. Việc lưu trữ các quyền đó trong bộ nhớ trong có thể tiết kiệm nhiều thời gian so với việc đọc dữ liệu từ bảng. Bộ đệm tên máy chủ (hostname): là bộ đệm chuyên dụng sử dụng cấu trúc ngăn xếp. Nó chứa tên máy chủ của tất cả các kết nối tới máy chủ. Đây là dữ liệu được yêu cầu thường xuyên. Ngoài các cơ chế lưu đệm trên, MySQL cũng sử dụng thêm một số cơ chế khác để làm tăng hiệu suất sử dụng của toàn bộ hệ thống. Như vậy, giống như mọi hệ QTCSDL quan hệ khác, quá trình truy vấn dữ liệu của MySQL cũng tuân thủ theo đúng tiến trình truy vấn gồm các bước cơ bản như phân tách, tối ưu hóa, thực thi truy vấn. MySQL hỗ trợ đầy đủ các câu lệnh SQL theo chuẩn ANSI, quá trình phân tách sử dụng kịch bản Lex – YACC, tối ưu truy vấn sử dụng chiến lược SELECT – PROJECT – JOIN, truy vấn được thực thi thông qua các phương thức thư viện chuẩn. Hơn nữa, MySQL còn sử dụng rất nhiều cơ chế lưu đệm hiệu quả để làm tăng hiệu suất truy vấn dữ liệu, đặc biệt là cơ chế lưu đệm các kết quả truy vấn. Đây chính là điểm độc đáo của MySQL. 1.4. Các đặc trưng của MySQL 1.4.1. Quản lí kết nối và an ninh Khi có một yêu cầu kết nối từ một máy khách tới một máy chủ, kết nối đó phải giành được một luồng (thread) riêng bên trong tiến trình của máy chủ. Các truy vấn trong kết nối thực thi trong một luồng đơn lẻ, nằm trên một lõi hay một CPU. Máy chủ lưu đệm các luồng, do đó không cần được tạo mới và hủy bỏ cho mỗi lần kết nối. Khi các máy khách (ứng dụng) kết nối tới máy chủ MySQL, máy chủ cần xác thực máy khách (hay ứng dụng) đó. Quá trình xác thực dựa trên tên người dùng, địa chỉ host ban đầu, và mật khẩu. Giấy chứng nhận X. 509 cũng có thể được sử dụng thông qua một kết nối Secure Sockets Layer (SSL). Khi một máy khách được kết nối, máy chủ xác thực liệu máy khách đó có quyền cho mỗi truy vấn mà nó đệ trình hay không. 17 1.4.2. Quản lí đồng thời Khi có nhiều truy vấn đồng thời yêu cầu dữ liệu tại cùng một thời điểm, MySQL sẽ xử lí như thế nào? MySQL thực hiện quản lí đồng thời tại 2 mức: mức máy chủ và mức storage engine. Ở đây chỉ xét quản lí đồng thời cho các thao tác đọc và ghi dữ liệu. Khi nhiều máy khách cùng đọc cùng một dữ liệu đồng thời, không có vấn đề gì xảy ra, do không có sự thay đổi dữ liệu. Nhưng chuyện gì sẽ xảy ra nếu một máy khách cố gắng đọc dữ liệu trong khi một máy khách khác đang thay đổi nó. Cũng giống như các hệ QTCSDL khác, MySQL sử dụng các cơ chế khóa để ngăn không cho máy khách đọc dữ liệu khi nó đang được thay đổi. MySQL sử dụng 2 loại khóa: - Khóa chia sẻ (shared lock - S) hay khóa đọc (read lock): các khóa đọc trên một tài nguyên được chia sẻ, nghĩa là nhiều máy khách có thể đọc một tài nguyên tại một thời điểm mà không ảnh hưởng đến nhau. - Khóa độc quyền (exclusive lock - X) hay khóa ghi (write lock): khi có một máy khách thực hiện thao tác ghi dữ liệu thì mọi thao tác đọc tới dữ liệu đó bị chặn. Các khóa độc quyền (X) có độ ưu tiên cao hơn các khóa chia sẻ (S). Vì thế, một yêu cầu khóa ghi sẽ được đẩy lên trước trong hàng đợi khóa ngay cả khi quá trình đọc đã sẵn sàng trên hàng đợi. Phạm vi khóa (Lock Granularity): Nhằm cải thiện hiệu suất sử dụng của một tài nguyên, nên lựa chọn những thứ sẽ bị khóa. Thay vì khóa toàn bộ tài nguyên, hiệu quả sẽ tốt hơn nếu chỉ khóa trên phần dữ liệu cần thay đổi. Tốt hơn nữa, chỉ khóa chính xác những dữ liệu định thay đổi. Giảm thiểu lượng dữ liệu bị khóa tại một thời điểm làm cho hiệu quả sử dụng đồng thời các tài nguyên tốt hơn, miễn là chúng không xung đột với nhau. Vấn đề là các khóa cũng sử dụng tài nguyên. Tất cả các bước trong tiến trình khóa gồm lấy một khóa, kiểm tra khóa đó có rỗi hay không, giải phóng một khóa, … đều có chi phí nhất định. Nếu một hệ thống dành quá nhiều thời gian quản lí khóa thay vì lưu trữ và truy tìm dữ liệu, hiệu suất có thể bị ảnh hưởng xấu. Một chiến lược khóa là sự thỏa hiệp giữa chi phí khóa và tính an toàn của dữ liệu, và sự thỏa hiệp đó ảnh hưởng tới hiệu suất. Hầu hết các máy chủ CSDL thương mại không có nhiều lựa chọn khóa nhưng MySQL lại cung cấp nhiều lựa chọn khóa thông qua các storage engine. Các storage engine có thể triển khai các chiến lược khóa và phạm vi khóa của riêng nó. Việc quản lí khóa là một quyết định rất quan trọng khi thiết kế storage engine. Sử dụng các khóa ở các mức nhất định nào đó có thể đạt được hiệu quả cao hơn trong trường hợp này nhưng lại kém hơn trong trường hợp khác. Bởi vì MySQL cung cấp nhiều storage engine với rất nhiều chiến lược khóa khác nhau nên 18 nó không yêu cầu một giải pháp chung. Tuy nhiên, MySQL thường sử dụng hai chiến lược khóa quan trọng sau: Các khóa mức bảng (Table lock): là chiến lược khóa cơ bản nhất và có chi phí thấp nhất trong MySQL. Một khóa bảng sẽ khóa toàn bộ bảng. Khi một máy khách muốn ghi dữ liệu vào một bảng (insert, delete, updade, …), nó yêu cầu một khóa ghi (X). Mọi thao tác đọc/ghi dữ liệu khác lên bảng đó đều bị chặn. Khi không đang thực hiện thao tác ghi trên bảng, các khóa đọc (S) được cấp cho người đọc, miễn là chúng không xung đột với các khóa đọc khác. Các biến thể của khóa mức bảng có thể đạt được hiệu suất tốt hơn trong một số tình huống đặc biệt. Chẳng hạn, các khóa mức bảng READ LOCAL cho phép một vài kiểu ghi dữ liệu đồng thời. Mặc dù các storage engine có thể quản lí các khóa của riêng nó nhưng bản thân MySQL cũng sử dụng các khóa mức bảng cho nhiều mục đích. Chẳng hạn, một máy chủ sử dụng một khóa mức bảng cho câu lệnh ALTER TABLE, không liên quan tới storage engine. Các khóa mức dòng (Row lock): triển khai khóa trên phạm vi từng dòng, là kiểu khóa cung cấp tính đồng thời nhất (và mang lại chi phí tốt nhất). Khóa mức dòng là một chiến lược được sử dụng phổ biến trong InnoDB, Falcon, và một số storage engine khác. Các khóa mức dòng được triển khai trong storage engine, chứ không phải trên máy chủ. Hầu hết các storage engine thực thi khóa theo cách riêng và máy chủ hoàn toàn không hay biết về cách thức triển khai các khóa này. 1.4.3. Giao tác Một giao tác là một tập hợp các truy vấn SQL được coi như một đơn vị công việc đơn lẻ. Nếu một máy CSDL có thể thực thi toàn bộ các câu truy vấn bên trong, giao tác thành công. Ngược lại, nếu có bất kì truy vấn nào trong chúng không thể được thực hiện bởi vì một đổ vỡ hay một nguyên nhân khác, không có câu lệnh nào trong số chúng được thực hiện. Giao tác có nghĩa hoặc là tất cả hoặc không gì cả. Mô hình ACID: Các giao tác tuân thủ mô hình ACID. ACID viết tắt của Atomicity, Consistency, Isolation, và Durability. Chúng là tiêu chuẩn quan hệ chặt chẽ mà một hệ thống xử lí giao tác tốt phải đạt được: Atomicity (tính nguyên tử) Một giao tác phải có chức năng như là một đơn vị công việc độc lập không thể chia nhỏ để toàn bộ giao tác hoặc được chấp nhận (commit) hoặc khôi phục lại (rollback). Giao tác không thể hoàn thành một phần: hoặc là tất cả hoặc không gì cả. Consistency (tính nhất quán) 19 Đảm bảo CSDL luôn luôn chuyển từ một trạng thái nhất quán này sang một trạng thái nhất quán khác. Isolation (tính cách ly) Kết quả của một giao tác không thể nhìn thấy bởi một giao tác khác cho đến khi giao tác đó hoàn thành. Durability (độ bền) Ngay sau khi commit, các thay đổi trong một giao tác là vĩnh viễn. Nghĩa là những thay đổi này sẽ không bị mất trong những đổ vỡ hệ thống. Tuy nhiên độ bền là một khái niệm mờ, bởi vì thực tế nó có rất nhiều mức độ khác nhau. Một vài chiến lược độ bền cung cấp một đảm bảo an toàn mạnh hơn những chiến lược khác, và không có chiến lược nào đảm bảo bền vững 100%. Máy chủ CSDL muốn đảm bảo ACID phải thực hiện rất nhiều thứ phức tạp. Ngay khi tăng phạm vi khóa, để đảm bảo an ninh thì máy chủ CSDL phải thực hiện nhiều việc hơn. Một máy chủ CSDL với các giao tác ACID cũng thường yêu cầu cấu hình CPU cao hơn, cần nhiều bộ nhớ trong và không gian đĩa hơn các máy chủ không chứa các giao tác ACID. MySQL quản lí giao tác trong các storage engine. Việc sử dụng các storage engine với tính tra lắp được khiến cho người dùng có thể linh hoạt quyết định khi nào ứng dụng cần tới các giao tác. Nếu không thực sự cần, nên sử dụng một storage engine không hỗ trợ giao tác hoặc sử dụng các bảng khóa (LOCK TABLE) để đạt được mức bảo vệ cần thiết. Các mức độ cách ly: Chuẩn SQL định nghĩa 4 mức độ cách ly với các luật về việc có thể nhìn thấy hay không nhìn thấy bên trong và bên ngoài một giao tác. Mức cách ly thấp hơn cho phép tính đồng thời cao hơn và có chi phí thấp hơn. Các mức độ cách ly được liệt kê theo thứ tự từ thấp đến cao, gồm: READ UNCOMMITED: tại mức này, các giao tác có thể nhìn thấy kết quả của các giao tác không được commit. Ít được sử dụng trong thực tế do hiệu quả không cao. Phép đọc dữ liệu chưa được commit được gọi là “dirty read”. READ COMMITED: là mức cách ly mặc định cho hầu hết các hệ CSDL (nhưng không phải cho MySQL). Tại mức này, một giao tác sẽ chỉ nhìn thấy những thay đổi của các giao tác đã được commit, và những thay đổi của nó không thể được nhìn thấy bởi các giao tác khác cho đến khi nó được commit. Mức này thường được gọi là đọc không lặp lại (nonrepeatable read), nghĩa là nếu thực hiện cùng một câu lệnh 2 lần thì dữ liệu nhìn thấy sẽ khác nhau. REPEATABLE READ: đảm bảo trong một giao tác, các dòng được đọc là như nhau với mọi thao tác đọc. Một vấn đề xảy ra ở mức cách ly này là: đọc ma - phantom read. Một phantom read có thể xảy ra khi xem các dòng, một giao tác khác chèn một
- Xem thêm -

Tài liệu liên quan