Thực tiễn tốt nhất để thay đổi lược đồ và di chuyển dữ liệu vào cơ sở dữ liệu trực tiếp mà không có thời gian chết?


43

Làm thế nào để bạn thực hiện thay đổi lược đồ cho cơ sở dữ liệu trực tiếp mà không có thời gian chết?

Chẳng hạn, giả sử tôi có cơ sở dữ liệu PostgreQuery với một bảng bao gồm nhiều dữ liệu người dùng khác nhau như địa chỉ email, v.v., tất cả đều được liên kết với người dùng cụ thể. Nếu tôi muốn chuyển địa chỉ email sang một bảng chuyên dụng mới, tôi phải thay đổi lược đồ và sau đó di chuyển dữ liệu email sang bảng mới. Làm thế nào điều này có thể được thực hiện mà không dừng ghi vào bảng gốc? Chắc chắn trong khi dữ liệu được ghi từ bảng cũ sang bảng mới, dữ liệu mới sẽ tiếp tục được ghi vào bảng cũ và bị bỏ lỡ, phải không?

Tôi đoán vấn đề này xuất hiện khá thường xuyên nhưng tôi không thể tìm thấy bất kỳ giải pháp tiêu chuẩn nào để giải quyết nó.

Bài viết này đề cập đến vấn đề nhưng tôi không thực sự hiểu bước 3. Anh ta nói viết vào cả hai bảng, sau đó di chuyển dữ liệu cũ từ bảng đầu tiên sang bảng mới. Làm thế nào để bạn chắc chắn rằng bạn chỉ di chuyển dữ liệu cũ?

(Tôi sử dụng PostgreSQL trên Heroku .)


2
Facebook đã phát triển một công cụ để làm điều này cho MySQL.
Nick Chammas

2
K. Scott Allen đã viết về một hệ thống quản lý các phiên bản lược đồ ở đây . Tôi đã tạo DbUpdater, một công cụ nguồn mở để triển khai lược đồ nhận biết phiên bản. Thêm tại đây - http://www.tewari.info/dbupdater
tro

@NickChammas Cảm ơn bạn đã chia sẻ điều đó. Tôi có rất nhiều câu hỏi về nó. Bạn có thể vui lòng đề xuất một hướng dẫn chi tiết hơn, tốt nhất là một video, giải thích những thứ như nhật ký bit, chỉ mục không được nhóm và trả lời các câu hỏi như - 1. Cách chọn dữ liệu từ bảng nguồn vào tải ngoài sẽ giảm tải so với sao chép đến đích bảng trực tiếp. 2. Khi nào giai đoạn sao chép sẽ kết thúc? Đây chỉ là một vài câu hỏi tôi có và tôi chỉ mới bắt đầu đọc nó.
Sandeepan Nath

@SandeepanNath - Xin lỗi, tôi không quen thuộc với công cụ của Facebook và vì vậy không thể chỉ cho bạn nhiều tài nguyên hơn. Tôi đã đọc một thông báo về nó và đăng bình luận của tôi nhiều năm trước, nhưng tôi chưa bao giờ sử dụng nó.
Nick Chammas

Câu trả lời:


27

Bạn gần như đã có câu trả lời của mình rồi:

  1. Tạo cấu trúc mới song song
  2. Bắt đầu viết cho cả hai cấu trúc
  3. Di chuyển dữ liệu cũ sang cấu trúc mới
  4. Chỉ viết và đọc cấu trúc mới
  5. Xóa các cột cũ

Đối với bước 3 , sử dụng một cái gì đó như thế này (trong một giao dịch):

Chèn những gì chưa có:

INSERT INTO new_tbl (old_id, data)
SELECT old_id, data
FROM   old_tbl
WHERE  NOT EXISTS (SELECT * FROM new_tbl WHERE new_tbl.old_id = old_tbl.old_id);

Cập nhật những gì đã thay đổi trong thời gian này:

UPDATE new_tbl
SET    data  = old.data
USING  old_tbl
WHERE  new_tbl.old_id = old_tbl.old_id
AND    new_tbl.data IS DISTINCT FROM old_tbl.data;

Dữ liệu mới sẽ không được chạm vào, vì nó giống hệt nhau ở cả hai nơi.


Tôi có một vài câu hỏi trong khi cố gắng hiểu kịch bản mà bạn đề xuất câu trả lời này - 1. Các thay đổi mã có được triển khai cùng với bắt đầu thay đổi db không? 2. Tại sao cần phải viết cho cả hai cấu trúc? 3. Tại sao cấu trúc mới không thể được đưa lên trước và sau đó dữ liệu hiện có được di chuyển và sau đó các thay đổi mã được triển khai sẽ tạo ra cấu trúc mới? 4. Tại sao cần phải tìm hiểu những gì không có (truy vấn đầu tiên của bạn)? Bạn đang đề xuất chèn trong nhiều lần thử?
Sandeepan Nath

2
@SandeepanNath, để trả lời câu hỏi 3 trong bình luận của bạn: bởi vì nếu bạn (a) đưa lên cấu trúc mới, (b) dữ liệu di chuyển đến nó, (c) thay đổi mã của bạn để dữ liệu ghi vào cấu trúc mới thay vì cái cũ, sau đó tất cả thay đổi dữ liệu được thực hiện giữa bước b và bước c sẽ chỉ tồn tại trong cấu trúc . Câu hỏi là làm thế nào để thay đổi lược đồ mà không có thời gian chết. Đọc câu trả lời này một lần nữa, cẩn thận.
tự đại diện
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.