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 25


ĐẠ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 – 20122

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


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 Mô tả
CSDL Cơ sở dữ liệu
Hệ QTCSDL Hệ quản trị cơ sở dữ liệu
MVCC (Multiversion concurrence control) Điều khiển đồng thời đa phiên bản DANH MỤC CÁC BẢNG
Tên bảng Trang
Bảng 2.1. Ma trận tương thích giữa các kiểu khóa trong InnoDB 32
Bảng 2.2. Bảng so sánh tính năng giữa CSDL quan hệ và NoSQL 35
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

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



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

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

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
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

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.


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

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ỉ

đ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

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.

và giao tác 2 sẽ khóa bản ghi có stock_id = 3. Sau đó, mỗi giao tác sẽ cố gắng chỉnh
sửa dòng thứ 2, nhưng lúc này cả 2 dòng đều đã bị khóa. Khi đó, cả 2 giao tác sẽ đợi
giao tác kia thực hiện xong và trừ khi có cái gì can thiệp, chúng sẽ đợi mãi mãi.
Các hệ CSDL đã sử dụng rất nhiều cách phát hiện deadlock khác nhau. Một số hệ
thống tinh vi hơn, như là InnoDB, có thể nhận ra vòng lặp vô hạn và đưa ra một thông
báo lỗi. Một số hệ thống khác lại sử dụng timeout như là một giải pháp. Các giao tác
sẽ kết thúc nếu một truy vấn vượt quá thời gian đợi (timeout) của khóa.
Thứ tự và cách thức khóa phụ thuộc vào từng storage engine, cho nên một
deadlock có thể xảy ra trong chuỗi câu lệnh của storage engine này nhưng vẫn chuỗi
câu lệnh đó trong storage engine khác thì không. Một số deadlock là không thể tránh
khỏi bởi vì dữ liệu thực sự xung đột nhưng một số khác có thể là do cách thức hoạt
động của storage engine.
Khi phá vỡ deadlock, các giao tác thường bị rollback, một phần hoặc toàn bộ.
Lưu biên bản giao tác: khiến cho giao tác được thực hiện hiệu quả hơn. Thay vì
chỉnh sửa bảng trên đĩa mỗi lần có thay đổi xảy ra, storage engine có thể chỉnh sửa trên
bản sao dữ liệu trong bộ nhớ trong của nó. Sau đó, storage engine ghi một bản ghi 21

những thay đổi lên một biên bản giao tác nằm trên đĩa. Cuối cùng, tại một thời điểm
sau đó, tiến trình có thể chỉnh sửa bảng trên đĩa. Như vậy vừa giảm được thời gian và
số lần truy cập đĩa lại vừa có tính bền vững do những thay đổi vẫn được ghi trên đĩa.
Điều này cũng cho quá trình xử lí nhanh hơn vì thay vì truy cập ngẫu nhiên trên nhiều
nơi thì có thể truy cập tuần tự trên một vùng nhỏ. Hầu hết các storage engine sử dụng
kỹ thuật này.
Nếu có một đổ vỡ sau khi một chỉnh sửa được ghi lên một biên bản giao tác nhưng
trước khi những thay đổi đó được tạo thành dữ liệu, storage engine có thể vẫn khôi
phục được những thay đổi khi khởi động lại. Phương thức khôi phục giữa các storage
engine là khác nhau.

Không chỉ MySQL, một số hệ CSDL khác như là Oracle, PostgreSQL, … cũng sử
dụng kĩ thuật này.
Điều khiển đồng thời đa phiên bản (MVCC) có thể coi là cải tiến của khóa mức
dòng. Nó tránh việc khóa tất cả các tài nguyên và trong nhiều trường hợp có thể đem
lại chi phí thấp hơn nhiều. Phụ thuộc vào cách triển khai, nó có thể cho phép đọc
không khóa, trong khi chỉ khóa những bản ghi cần thiết khi thực hiện thao tác ghi.
MVCC hoạt động bằng cách giữ một snapshot của dữ liệu của một vài thời điểm.
Do đó, giao tác có thể nhìn thấy dữ liệu nhất quán mà không quan tâm tới chúng đã
thực thi bao lâu. Điều đó cũng có nghĩa là các giao tác khác nhau có thể nhìn thấy
những dữ liệu khác nhau trong cùng một bảng tại cùng một thời điểm. Các storage
engine khác nhau triển khai điều khiển đồng thời đa phiên bản khác nhau.
1.4.5. Chỉ mục
Chỉ mục là cấu trúc dữ liệu hỗ trợ MySQL tìm kiếm dữ liệu một cách hiệu quả.
Chỉ mục (đôi khi còn gọi là “khóa”) càng quan trọng khi dữ liệu càng lớn. Những cơ
sở dữ liệu nhỏ có thể đạt hiệu suất tốt ngay cả khi không có chỉ mục nhưng khi dữ liệu
lớn hơn thì hiệu suất giảm một cách nhanh chóng. MySQL thường triển khai các cơ
chế chỉ mục trong các storage engine. Hơn nữa, cách triển khai chúng trong từng
storage engine là không giống nhau: các storage engine khác nhau triển khai những
kiểu chỉ mục khác nhau; không phải mọi engine đều hỗ trợ mọi loại chỉ mục; thậm chí
khi nhiều engine hỗ trợ cùng một loại chỉ mục thì sự triển khai chúng cũng không
giống nhau. Mặc dù các kiểu chỉ mục trong storage engine là vô cùng phong phú
nhưng vẫn có một số kiểu chỉ mục thường được hỗ trợ. Sau đây là một số loại chỉ mục
như thế:
Các chỉ mục B-Tree: tất cả các giá trị được lưu trữ theo thứ tự, mỗi trang lá có
cùng khoảng cách tới gốc. Mỗi nút chứa dữ liệu của nó cùng với con trỏ tới con của
nó. Quá trình tìm kiếm diễn ra từ gốc và tìm kiếm trên cây dựa trên khóa tìm kiếm. Nó
khiến cho quá trình tìm kiếm diễn ra nhanh chóng mà không phải thăm toàn bộ bảng
để tìm dữ liệu. Thay vào đó, bắt đầu từ gốc, đi theo các con trỏ tới các nút con thỏa
mãn điều kiện nào đó (ví dụ như key >value hoặc <=value) cho đến khi tìm thấy lá cần
tìm hoặc khẳng định rằng giá trị đó không tồn tại.

để hạn chế không gian. Tiền tố nên đủ dài để khiến cho chỉ mục có tính hữu dụng gần
như là khi lập chỉ mục trên toàn bộ cột.
Chỉ mục cụm (clustered index): không phải là một kiểu chỉ mục, đó là một
hướng tiếp cận lưu trữ dữ liệu. Khi một bảng có một chỉ mục cụm, các dòng của nó
thực tế được lưu trữ trên các lá, các nút khác chỉ chứa các cột chỉ mục. Thuật ngữ
“phân cụm” để chỉ rằng các dòng với các giá trị khóa liền kế được lưu trữ gần nhau.
Trên mỗi bảng chỉ có thể có duy nhất một chỉ mục cụm do không thể lưu trữ các dòng
tại 2 nơi cùng lúc được.
Lợi ích của chỉ mục cụm:
 Lưu trữ các dữ liệu liên quan gần nhau
 Truy cập dữ liệu nhanh hơn. Một chỉ mục cụm giữ cả chỉ mục và dữ liệu trong
một cấu trúc B-Tree, vì thế khi tìm kiếm các dòng từ một chỉ mục cụm thường
nhanh hơn so với các trường hợp khác.
Chỉ mục cuộn (covering index): Các truy vấn sử dụng các chỉ mục cuộn sử dụng
các giá trị khóa chính chứa tại các nút lá. Chỉ mục là một cách để tìm kiếm các dòng
một cách hiệu quả, nhưng MySQL cũng có thể sử dụng một chỉ mục để tìm kiếm dữ
liệu trong một cột, vì thế nó không cần phải đọc dòng đó. Các nút lá chứa giá trị mà 24

chúng chỉ mục. Một chỉ mục chứa tất cả dữ liệu cần thiết thỏa mãn một truy vấn gọi là
chỉ mục cuộn.
Chỉ mục gói (hay chỉ mục nén tiền tố): để giảm kích thước chỉ mục, cho phép
nhiều chỉ mục hơn phù hợp với bộ nhớ trong và cải thiện đáng kể hiệu suất trong một
số trường hợp.
MyISAM gói mỗi khối chỉ mục bằng cách lưu trữ đầy đủ giá trị đầu tiên của khối,
sau đó lưu trữ mỗi giá trị bổ sung trong khối đó bằng cách ghi số lượng các byte có
cùng tiền tố và dữ liệu khác nhau của hậu tố. Ví dụ, nếu giá trị đầu tiên là “perform”
và giá trị thứ hai là “performance” thì giá trị thứ 2 được lưu trữ là “7,ance”.


Nhờ tải bản gốc

Tài liệu, ebook tham khảo khác

Music ♫

Copyright: Tài liệu đại học © DMCA.com Protection Status