InnoDB lưu trữ dữ liệu giao dịch ở đâu trước khi cam kết?


12

Tôi đã thực hiện một số thử nghiệm bằng cách sử dụng READ_COMMITTEDREAD_UNCOMMITTEDở nhà, sử dụng công nghệ JDBC.

Tôi thấy rằng READ_UNCOMMITTEDthực sự có thể đọc dữ liệu không được cam kết, ví dụ: dữ liệu từ một số giao dịch chưa được cam kết (có thể thực hiện truy vấn CẬP NHẬT).

Câu hỏi

  • Trường hợp dữ liệu không được cam kết được lưu trữ, sao cho một READ_UNCOMMITTEDgiao dịch có thể đọc dữ liệu không được cam kết từ một giao dịch khác?
  • Tại sao READ_COMMITTEDgiao dịch không thể đọc dữ liệu không được cam kết, tức là thực hiện "đọc bẩn"? Cơ chế nào thi hành hạn chế này?

Câu trả lời:


11

" Trường hợp dữ liệu không được cam kết được lưu trữ, sao cho giao dịch READ_UNCOMMITTED có thể đọc dữ liệu không được cam kết từ một giao dịch khác? "

Các phiên bản bản ghi không được cam kết mới (PK cụm) được coi là phiên bản "hiện tại" của bản ghi trên trang. Vì vậy, chúng có thể được lưu trữ trong vùng đệm và / hoặc trong vùng bảng (ví dụ: tablename.ibd). Các giao dịch sau đó cần xây dựng một snapshot / view trong bất kỳ thứ gì ngoài READ-UNCOMMITTED, cần xây dựng một phiên bản trước của hàng (theo danh sách lịch sử) bằng cách sử dụng các bản ghi UNDO (được lưu trữ trong không gian bảng hệ thống ). Khi đọc bản ghi không được cam kết, InnoDB cũng có thể cần đọc một số bản ghi chỉ mục phụ không được cam kết từ Bộ đệm thay đổi và áp dụng chúng trước khi trình bày bản ghi lại cho người dùng.

Đây là hành vi có thể khiến cho các rollback trong InnoDB trở nên đắt đỏ. Đó là yếu tố lớn cũng có thể dẫn đến các vấn đề về hiệu suất tiềm ẩn từ các giao dịch nhàn rỗi đang giữ các bản ghi được cập nhật, vì các giao dịch đó sẽ chặn hoạt động thanh lọc và danh sách lịch sử của các phiên bản bản ghi cũ tăng lên, và các bản ghi UNDO cần để xây dựng lại các phiên bản cũ đó theo yêu cầu, sẽ tiếp tục phát triển. Nó làm chậm các giao dịch mới cần đọc phiên bản cũ hơn / đã cam kết, vì chúng cần duyệt qua danh sách lịch sử dài hơn và dài hơn - đó là danh sách các bản ghi UNDO được liên kết đơn lẻ - và thực hiện nhiều công việc hơn để xây dựng lại phiên bản cũ của hồ sơ. Vì vậy, cuối cùng bạn sử dụng rất nhiều chu kỳ CPU (không đề cập đến các nguyên hàm khóa bên trong: mutexes, rw_locks, semaphores, v.v.

Hy vọng rằng có ý nghĩa? :)

Là một FYI, trong MySQL 5.7, bạn có thể di chuyển không gian bảng UNDO và đăng xuất khỏi không gian bảng hệ thống và để chúng tự động cắt ngắn. Chúng có thể phát triển khá lớn nếu bạn có một giao dịch chạy dài ngăn chặn các hoạt động thanh lọc, dẫn đến độ dài danh sách lịch sử rất dài và ngày càng tăng. Việc chúng được lưu trữ trong không gian bảng hệ thống là nguyên nhân phổ biến nhất của tệp ibdata1 lớn / đang phát triển, do đó không thể cắt / thu nhỏ / hút bụi để sau đó lấy lại không gian đó.


4

Bạn đã hỏi

dữ liệu không được cam kết được lưu trữ ở đâu, sao cho giao dịch READ_UNCOMMITTED có thể đọc dữ liệu không được cam kết từ một giao dịch khác?

Để trả lời câu hỏi của bạn, bạn cần biết Kiến trúc InnoDB trông như thế nào.

Hình ảnh sau đây được tạo ra cách đây nhiều năm bởi Percona CTO Vadim Tkachenko

Kiến trúc InnoDB

Theo Tài liệu MySQL về Mô hình giao dịch và khóa InnoDB

CAM KẾT có nghĩa là những thay đổi được thực hiện trong giao dịch hiện tại được thực hiện vĩnh viễn và hiển thị cho các phiên khác. Mặt khác, một câu lệnh ROLLBACK hủy bỏ tất cả các sửa đổi được thực hiện bởi giao dịch hiện tại. Cả CommIT và ROLLBACK đều phát hành tất cả các khóa InnoDB đã được đặt trong giao dịch hiện tại.

Vì CAM KẾT và ROLLBACK chi phối khả năng hiển thị dữ liệu, ĐỌC CAM KẾT và ĐỌC KHÔNG HOÀN THÀNH sẽ phải dựa vào các cấu trúc và cơ chế ghi lại các thay đổi

  1. Phân đoạn rollback / Hoàn tác không gian
  2. Làm lại Nhật ký
  3. Các khoảng trống khóa chống lại (các) bảng có liên quan

Phân đoạn rollback và Hoàn tác không gian sẽ biết dữ liệu đã thay đổi trông như thế nào trước khi thay đổi được áp dụng. Nhật ký Redo sẽ biết những thay đổi nào sẽ được đưa ra để cập nhật dữ liệu.

Bạn cũng đã hỏi

tại sao giao dịch READ_COMMITTED không thể đọc dữ liệu không được cam kết, tức là thực hiện "đọc bẩn"? Cơ chế nào thi hành hạn chế này?

Làm lại Nhật ký, Hoàn tác không gian và các hàng đã khóa được sử dụng. Bạn cũng phải xem xét anh ấy Bộ đệm InnoDB (nơi bạn có thể đo các trang bẩn bằng innodb_max_denty_pages_pct , innodb_buffer_pool_pages_dentyinnodb_buffer_pool_bytes_denty ).

Trong trường hợp này, ĐỌC CAM KẾT sẽ biết dữ liệu nào xuất hiện vĩnh viễn. Do đó, không cần phải tìm các trang bẩn mà không được cam kết. ĐỌC TIẾNG VIỆT sẽ không còn gì nữa khi một bản đọc bẩn đã được cam kết. ĐỌC UNCOMMITTED sẽ tiếp tục biết những hàng nào sẽ bị khóa và những bản ghi làm lại đã được đọc hoặc bỏ qua để làm cho dữ liệu hiển thị.

Để hiểu đầy đủ về Khóa hàng để quản lý cách ly, vui lòng đọc Mô hình giao dịch và khóa của InnoDB


1
Trước tiên, cảm ơn bạn đã trả lời và sửa đổi bài đăng của tôi ... Vì vậy, trước khi CAM KẾT, những thay đổi không hiển thị cho những người dùng khác của hệ thống? Ở đây người dùng có nghĩa đen là một giao dịch, phải không? Vì READ UNCOMMITTED có thể đọc dữ liệu không được cam kết, mức độ cô lập này đọc dữ liệu này ở đâu? Có thể có nhiều hơn một nguồn dữ liệu không được cam kết cho một mục dữ liệu cụ thể trong cơ sở dữ liệu không? Nếu vậy, phần dữ liệu không được cam kết nào sẽ được đọc?
Shuzheng 7/10/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.