2009-03-17 43 views
28

Đôi khi chúng ta sẽ sớm cần thay đổi lược đồ cho cơ sở dữ liệu sản xuất của mình. Tuy nhiên, chúng ta cần giảm thiểu thời gian chết cho nỗ lực này, các câu lệnh ALTER TABLE sẽ chạy khá lâu. Bảng lớn nhất của chúng tôi có 150 triệu bản ghi, tệp bảng lớn nhất là 50G. Tất cả các bảng đều là InnoDB, và nó được thiết lập thành một tệp dữ liệu lớn (thay vì một tệp cho mỗi bảng). Chúng tôi đang chạy MySQL 5.0.46 trên máy 8 lõi, bộ nhớ 16G và cấu hình RAID10.Tối ưu hóa MySQL cho ALTER BẢNG của InnoDB

Tôi có một số kinh nghiệm với điều chỉnh MySQL, nhưng điều này thường tập trung vào đọc hoặc viết từ nhiều khách hàng. Có rất nhiều thông tin được tìm thấy trên Internet về chủ đề này, tuy nhiên, có vẻ như có rất ít thông tin sẵn có về các phương pháp hay nhất để (tạm thời) điều chỉnh máy chủ MySQL của bạn để tăng tốc ALTER TABLE trên các bảng InnoDB hoặc cho INSERT INTO. CHỌN TỪ (chúng tôi có thể sẽ sử dụng điều này thay vì ALTER TABLE để có thêm một số cơ hội để tăng tốc độ lên một chút).

Thay đổi lược đồ mà chúng tôi dự định làm là thêm cột nguyên vào tất cả các bảng và đặt làm khóa chính, thay vì khóa chính hiện tại. Chúng ta cũng cần giữ cột 'cũ' để ghi đè các giá trị hiện tại không phải là một lựa chọn.

Cài đặt lý tưởng để thực hiện tác vụ này nhanh nhất có thể là gì?

+0

Liên quan: http://stackoverflow.com/q/9524938/632951 – Pacerier

Trả lời

-4

Tôi thực sự không biết cách tối ưu hóa điều đó, nhưng thường là cách hay để đặt trang web ở chế độ ngoại tuyến trước khi thực hiện các cập nhật đó.

Sau đó, bạn có thể chạy các tập lệnh DB của mình vào lúc 3 giờ sáng, do đó, nó không quan trọng nếu thời gian chết lâu hơn lý tưởng.

+0

Có - chúng tôi sẽ đưa trang web xuống vào ban đêm để thực hiện tác vụ này. Nhưng với các bảng lớn như vậy ALTER TABLE có thể chạy trong nhiều giờ, và điều đó có lẽ sẽ không phù hợp với một đêm: ( – schuilr

+0

Có thể bạn muốn chạy tập lệnh trong một máy chủ riêng biệt với một khoảng thời gian DB sản xuất như thế nào Hy vọng rằng, bạn sẽ nhận được một bất ngờ tốt đẹp! :) – Seb

+0

Vâng, chúng tôi đang chuẩn bị một môi trường QA cho việc này. Không thể tối ưu hóa mà không kiểm tra các tối ưu của bạn;) – schuilr

15

Bạn cần suy nghĩ kỹ hơn về các yêu cầu của mình.

Ở mức đơn giản nhất, cách "nhanh nhất" để thay đổi bảng là thực hiện điều đó trong một vài câu lệnh ALTER TABLE nhất có thể, tốt nhất là một. Điều này là do MySQL sao chép dữ liệu của bảng để thay đổi lược đồ và thực hiện mười lăm thay đổi trong khi thực hiện một bản sao rõ ràng (và thực sự là) nhanh hơn sao chép bảng mười lăm lần, thực hiện một thay đổi tại một thời điểm.

Nhưng tôi nghi ngờ bạn đang hỏi cách thực hiện thay đổi này với thời gian ngừng hoạt động ít nhất. Cách tôi sẽ làm điều đó, về cơ bản bạn tổng hợp cách một khối không ALTER TABLE sẽ hoạt động. Nhưng nó có một số yêu cầu bổ sung:

  1. bạn cần cách theo dõi dữ liệu đã thêm và thay đổi, chẳng hạn như trường ngày "sửa đổi" cho trường sau hoặc trường AUTO_INCREMENT cho trường cũ.
  2. bạn cần không gian để có hai bản sao của bảng trên cơ sở dữ liệu.
  3. bạn cần một khoảng thời gian mà thay đổi để bảng sẽ không nhận được quá xa phía trước của một bản chụp

Kỹ thuật cơ bản là như bạn đề nghị, ví dụ sử dụng một INSERT INTO ... SELECT .... Ít nhất bạn đang ở phía trước bởi vì bạn đang bắt đầu với một bảng InnoDB, do đó, SELECT sẽ không chặn. Tôi khuyên bạn nên thực hiện ALTER TABLE trên bảng trống mới, sẽ lưu MySQL sao chép tất cả dữ liệu một lần nữa, điều này có nghĩa là bạn cần phải liệt kê tất cả các trường một cách chính xác trong câu lệnh INSERT INTO ... SELECT .... Sau đó, bạn có thể làm một tuyên bố đơn giản RENAME để trao đổi nó qua. Sau đó, bạn cần phải thực hiện một số khác INSERT INTO ... SELECT ... WHERE ... và có lẽ là UPDATE ... INNER JOIN ... WHERE ... để lấy tất cả dữ liệu đã sửa đổi.Bạn cần làm INSERTUPDATEnhanh chóng hoặc mã của bạn sẽ bắt đầu thêm hàng mới và cập nhật cho ảnh chụp nhanh của bạn mà sẽ can thiệp vào cập nhật của bạn. (Bạn sẽ không gặp vấn đề này nếu bạn có thể đặt ứng dụng của mình vào chế độ bảo trì trong vài phút từ trước RENAME.)

Ngoài ra, có một số cài đặt liên quan đến bộ đệm và phím bạn chỉ có thể thay đổi phiên có thể giúp di chuyển dữ liệu chính. Những thứ như read_rnd_buffer_sizeread_buffer_size sẽ hữu ích để tăng.

11

Thật không may, điều này không phải lúc nào cũng đơn giản như staticsan dẫn đầu trong câu trả lời của anh ấy. Tạo bảng mới trong khi trực tuyến và di chuyển dữ liệu trở nên dễ dàng và thực hiện dọn dẹp trong khi ở chế độ bảo trì cũng đủ khả năng, tuy nhiên, thao tác Mysql RENAME sẽ tự động thao tác bất kỳ tham chiếu khóa ngoài nào tới bảng cũ của bạn. Điều này có nghĩa là bất kỳ tham chiếu khóa ngoài nào đến bảng gốc sẽ vẫn trỏ đến bất kỳ thứ gì bạn đổi tên bảng thành. Vì vậy, nếu bạn có bất kỳ tham chiếu khóa lạ nào vào bảng bạn đang cố thay đổi, bạn sẽ thay đổi các bảng đó để thay thế tham chiếu đến bảng mới của bạn hoặc tệ hơn nếu bảng đó lớn, bạn phải lặp lại quá trình với bảng lớn số hai.

Một cách tiếp cận khác đã làm việc cho chúng tôi trong quá khứ là sắp xếp một bộ các bản sao Mysql xử lý thay đổi. Tôi không phải là người giỏi nhất để nói chuyện với quá trình này, nhưng về cơ bản nó bao gồm việc nhân rộng một nô lệ, chạy bản vá trên cá thể đó, quay sao chép lại khi bảng thay đổi được hoàn thành để nó bắt kịp trên bản sao. Một khi nhân rộng bắt kịp, bạn đặt trang web vào chế độ bảo trì (nếu cần) để chuyển từ chủ của bạn sang nô lệ được vá mới này làm cơ sở dữ liệu chính mới.

Điều duy nhất tôi không thể nhớ là chính xác khi bạn chỉ các nô lệ khác tại bản chính mới để họ cũng nhận được thay đổi được áp dụng. Một cảnh báo trước cho quá trình này, chúng tôi thường sử dụng tính năng này để cuộn các bản vá lỗi trước khi mã cần thay đổi hoặc sau khi mã đã thay đổi để không còn tham chiếu đến các cột/khóa.

+0

Tôi đã không nghĩ đến các khóa ngoại. Tôi là một DBA, nơi tôi đã sử dụng kỹ thuật mà tôi mô tả, chúng tôi đã không sử dụng các khóa ngoại khi ứng dụng tin tưởng và chỉ xử lý tất cả những điều đó. – staticsan

12
  1. Thiết lập nô lệ
  2. Dừng sao chép.
  3. Hãy ALTER về nô lệ
  4. Hãy nô lệ bắt kịp các bậc thầy
  5. hoán đổi chủ và nô lệ, vì vậy nô lệ trở thành máy chủ sản xuất với cấu trúc thay đổi và thời gian chết tối thiểu
15

Bạn có thể muốn nhìn vào pt-online-schema-change từ Percona bộ công cụ. Về cơ bản những gì nó làm là:

  • Sao chép cấu trúc bảng gốc, chạy ALTER.
  • Sao chép các hàng từ bảng cũ sang bảng mới được tạo.
  • Sử dụng trình kích hoạt để theo dõi và đồng bộ hóa các thay đổi trong khi sao chép.
  • Khi mọi thứ kết thúc, nó hoán đổi bảng bằng cách đổi tên cả hai.

Hoạt động rất tốt cho cơ sở dữ liệu cá thể đơn lẻ, nhưng có thể khá phức tạp nếu bạn sử dụng bản sao và không thể dừng nô lệ và xây dựng lại chúng sau này.

Ngoài ra còn có một hội thảo trên web về điều này here.

PS: Tôi biết đó là câu hỏi cũ, chỉ trả lời trong trường hợp ai đó truy cập thông qua công cụ tìm kiếm.

+1

Một lưu ý từ các tài liệu thay đổi sơ đồ trực tuyến pt: Việc sử dụng các trình kích hoạt có nghĩa là công cụ sẽ không hoạt động nếu bất kỳ trình kích hoạt nào đã được xác định trên bảng. – cgaldiolo

5

Tôi đã thử nghiệm các chiến lược khác nhau để tăng tốc một bảng thay đổi. Cuối cùng tôi nhận được khoảng 10 lần tăng tốc trong trường hợp cụ thể của tôi. Kết quả có thể có hoặc không áp dụng cho trường hợp của bạn. Tuy nhiên, dựa trên điều này tôi sẽ đề nghị thử nghiệm với các tham số kích thước tập tin/bộ đệm log của InnoDB.

Nói tóm lại, chỉ tăng innodb_log_file_size và innodb_log_buffer_size đã có một ảnh hưởng đáng kể (Hãy cẩn thận! Thay đổi innodb_log_file_size là rủi ro. Xem bên dưới để biết thêm).

Dựa trên tốc độ ghi dữ liệu thô (iostat) và hoạt động cpu, nút cổ chai là dựa trên io, nhưng không phải thông lượng dữ liệu. Trong 500s nhanh hơn chạy thông lượng ghi là ít nhất là trong cùng một ballpark mà bạn mong chờ từ đĩa cứng.

Cố gắng tối ưu hóa hiệu suất:

Thay đổi innodb_log_file_size có thể nguy hiểm. Xem http://www.mysqlperformanceblog.com/2011/07/09/how-to-change-innodb_log_file_size-safely/ Kỹ thuật (di chuyển tệp) được giải thích trong liên kết hoạt động tốt trong trường hợp của tôi.

Đồng thời xem http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/ để biết thông tin về kích thước nhật ký và điều chỉnh nhật ký. Một nhược điểm của các tệp nhật ký lớn hơn là thời gian khôi phục lâu hơn sau sự cố.

thử nghiệm chạy và timings thô:

  • Các dữ liệu tải đơn giản để một bảng tươi createad: 6500s
  • tải dữ liệu w. innodb_log_file_size = 200M, innodb_log_buffer_size = 8M, innodb_buffer_pool_size = 2200M, autocommit = 0; unique_checks = 0, foreign_key_checks = 0: 500s
  • tải dữ liệu w. innodb_log_file_size = 200M, innodb_log_buffer_size = 8M: 500s
  • Bảng thay đổi thẳng tương đương w.datainnodb_log_file_size = 200M, innodb_log_buffer_size = 8M: 500s

kiểm tra chi tiết: Bảng: InnoDB, hàng 6M, 2.8G trên đĩa, tập tin duy nhất (tùy chọn innodb_file_per_table), khóa chính là 1 số nguyên, 2 unque chế/chỉ số, 8 cột, trung bình chiều dài hàng 218 byte. Máy chủ: Ubuntu 12.04, x86_64, máy ảo, 8 lõi, 16GB, đĩa tiêu chuẩn sata, không có đột kích, không hoạt động cơ sở dữ liệu, trừ đi các hoạt động quy trình khác, hoạt động nhỏ trong các máy ảo nhỏ hơn và nhỏ hơn nhiều. Mysql 5.1.53. Cấu hình máy chủ ban đầu là khá mặc định ngoại trừ tăng innodb_buffer_pool_size là 1400M. Bảng thay đổi thêm 2 cột nhỏ. Tôi đã không đồng hồ bảng thay đổi thô, nhưng thay vào đó thử nghiệm với tuyên bố tải dữ liệu tương đương, cuối cùng tôi đã làm bảng thay đổi thẳng và có kết quả tương đương.

Câu hỏi này có liên quan đến câu hỏi ít nhất sau:

+0

Câu trả lời tuyệt vời, điều này xứng đáng được nhiều phiếu bầu hơn nữa. Cảm ơn bạn đã xuất bản nghiên cứu và kết quả của mình. – culix

Các vấn đề liên quan