2008-08-29 37 views
14

Có lẽ rủi ro lớn nhất trong việc đẩy tính năng mới để sống nằm với các sửa đổi cơ sở dữ liệu được yêu cầu bởi mã mới. Trong Rails, tôi tin rằng họ có 'di chuyển', trong đó bạn có thể lập trình thay đổi cho máy chủ phát triển của mình, và sau đó thực hiện các thay đổi tương tự cùng với mã sử dụng lược đồ đã sửa đổi. Và cuộn cả hai lại nếu cần, theo cách đồng bộ.Di chuyển các thay đổi cơ sở dữ liệu từ phát triển sang sống

Có ai đi qua một bộ công cụ tương tự cho PHP/MySQL không? Rất thích nghe về nó, hoặc bất kỳ giải pháp lập trình hoặc xử lý nào để giúp việc này ít rủi ro hơn ...

Trả lời

2

Symfony có một plugin được gọi là sfMigrationsLight xử lý di chuyển cơ bản. CakePHP cũng có di chuyển.

Vì lý do nào đó, hỗ trợ di chuyển chưa bao giờ thực sự là ưu tiên cao đối với hầu hết các khung công tác PHP và ORM.

5

Tôi chưa bao giờ gặp một công cụ có thể thực hiện công việc. Thay vào đó, tôi đã sử dụng các tệp riêng lẻ, được đánh số để tôi biết thứ tự chạy chúng: về bản chất, một phiên bản thủ công của các lần di chuyển Rails, nhưng không có khôi phục.

Dưới đây là các loại điều tôi đang nói về:

000-clean.sql   # wipe out everything in the DB 
001-schema.sql  # create the initial DB objects 
002-fk.sql   # apply referential integrity (simple if kept separate) 
003-reference-pop.sql # populate reference data 
004-release-pop.sql # populate release data 
005-add-new-table.sql # modification 
006-rename-table.sql # another modification... 

Tôi chưa bao giờ thực sự chạy vào bất kỳ vấn đề làm điều này, nhưng nó không phải là rất thanh lịch. Bạn có thể theo dõi các tập lệnh nào cần chạy cho một bản cập nhật nhất định (một lược đồ đánh số thông minh hơn có thể hữu ích). Nó cũng hoạt động tốt với kiểm soát nguồn.

Xử lý các giá trị khóa thay thế (từ cột tự động) có thể là một nỗi đau, vì cơ sở dữ liệu sản xuất có thể có giá trị khác với DB phát triển. Vì vậy, tôi cố gắng không bao giờ đề cập đến một giá trị khóa thay thế bằng chữ trong bất kỳ kịch bản sửa đổi nào của tôi nếu có thể.

5

Tôi không tin tưởng di chuyển có lập trình. Nếu đó là một thay đổi đơn giản, chẳng hạn như thêm cột NULLable, tôi sẽ chỉ thêm nó trực tiếp vào máy chủ trực tiếp. Nếu nó phức tạp hơn hoặc yêu cầu thay đổi dữ liệu, tôi sẽ viết một cặp tệp di chuyển SQL và kiểm tra chúng dựa trên cơ sở dữ liệu bản sao.

Khi sử dụng di chuyển, luôn luôn kiểm tra di chuyển quay lại. Đó là nút "oh shit" khẩn cấp của bạn.

2

Tôi sử dụng SQLyog để sao chép cấu trúc và tôi LUÔN LUÔN, hãy để tôi lặp lại LUÔN thực hiện sao lưu trước.

3

Tôi đã sử dụng công cụ này trước và nó hoạt động hoàn hảo.

http://www.mysqldiff.org/

Phải mất như một đầu vào hoặc là một kết nối DB hoặc một tập tin SQL, và so sánh nó với cùng (hoặc một kết nối DB này hay cách khác tập tin SQL). Nó có thể nhổ ra SQL để thực hiện các thay đổi hoặc thực hiện các thay đổi cho bạn.

3

@ [yukondude]

Tôi đang sử dụng Perl bản thân mình, và tôi đã đi xuống con đường di cư Rails kiểu bán tay trong cùng một cách.

Những gì tôi đã làm là có một bảng "phiên bản" đơn với một cột "phiên bản", chứa một hàng duy nhất của một số là phiên bản lược đồ hiện tại.Sau đó, nó đã được (khá) tầm thường để viết một kịch bản để đọc số đó, nhìn vào một thư mục nhất định và áp dụng tất cả các di chuyển đánh số để có được từ đó đến đây (và sau đó cập nhật số).

Trong môi trường dev/giai đoạn của tôi, tôi thường xuyên (thông qua tập lệnh khác) kéo dữ liệu sản xuất vào cơ sở dữ liệu dàn dựng và chạy tập lệnh di chuyển. Nếu bạn làm điều này trước khi bạn phát trực tiếp, bạn sẽ chắc chắn rằng việc di chuyển sẽ hoạt động. Rõ ràng bạn kiểm tra rộng rãi trong môi trường dàn dựng của bạn.

Tôi gắn thẻ mã mới và di chuyển bắt buộc trong một thẻ kiểm soát phiên bản. Để triển khai lên stage hoặc live bạn chỉ cập nhật mọi thứ cho thẻ này và chạy script di chuyển khá nhanh. (Bạn có thể muốn sắp xếp thời gian ngừng hoạt động ngắn nếu nó thực sự thay đổi giản đồ.)

1

Khá nhiều những gì Lot105 mô tả.

Mỗi lần di chuyển cần tập lệnh áp dụng và quay lại và bạn có một số loại tập lệnh kiểm soát để kiểm tra (các) di chuyển nào cần được áp dụng và áp dụng chúng theo thứ tự thích hợp.

Mỗi nhà phát triển sau đó giữ db của họ đồng bộ bằng cách sử dụng lược đồ này và khi áp dụng cho sản xuất, các thay đổi có liên quan sẽ được áp dụng. Các kịch bản rollback có thể được giữ lại để thay đổi nếu điều đó trở nên cần thiết.

Một số thay đổi không thể thực hiện được bằng tập lệnh ALTER đơn giản như công cụ như sqldiff sẽ tạo; một số thay đổi không yêu cầu thay đổi lược đồ mà là thay đổi có lập trình đối với dữ liệu hiện có. Vì vậy, bạn có thể không thực sự khái quát, đó là lý do tại sao bạn cần một kịch bản do con người biên tập.

0

Tôi luôn muốn giữ trang web phát triển của mình trỏ đến cùng một DB làm trang web trực tiếp. Điều này nghe có vẻ nguy hiểm lúc đầu nhưng thực tế nó giải quyết được nhiều vấn đề. Nếu bạn có hai trang web trên cùng một máy chủ trỏ đến cùng một DB, bạn sẽ có được một thời gian thực và xem chính xác những gì người dùng của bạn sẽ thấy khi nó hoạt động.

Bạn sẽ chỉ có 1 cơ sở dữ liệu và miễn là bạn làm cho chính sách không bao giờ xóa cột khỏi bảng, bạn biết mã mới của mình sẽ khớp với cơ sở dữ liệu bạn đang sử dụng.

Ngoài ra, việc di chuyển cũng ít tàn phá hơn đáng kể. Bạn chỉ cần di chuyển qua các tập lệnh PHP và chúng đã được thử nghiệm bằng cách sử dụng cùng một DB.

Tôi cũng có xu hướng tạo liên kết tượng trưng đến bất kỳ thư mục nào là mục tiêu để người dùng tải lên. Điều này có nghĩa là không có sự nhầm lẫn về các tệp người dùng nào đã được cập nhật.

Một ảnh hưởng phụ khác là tùy chọn chuyển qua một nhóm nhỏ 'người thử nghiệm beta' để sử dụng trang web trong sử dụng hàng ngày. Điều này có thể dẫn đến nhiều phản hồi mà bạn có thể triển khai trước khi khởi chạy công khai.

Điều này có thể không hoạt động trong mọi trường hợp nhưng tôi đã bắt đầu di chuyển tất cả các cập nhật của tôi cho mô hình này. Nó gây ra sự phát triển và ra mắt mượt mà hơn nhiều.

+0

Làm cách nào để xử lý việc đổi tên cột? Việc đổi tên nhanh sẽ phá vỡ môi trường sản xuất của bạn, phải không? –

+0

@Kevin Pang - đó là sự thật nhưng tôi không đổi tên cột của tôi quá thường xuyên. Tôi đã tìm thấy con quỷ nhỏ hơn là để lại tên cột theo cách của chúng. Nó làm cho tôi suy nghĩ cẩn thận về tên cột nhưng tôi cũng thấy đó là một sự xuất hiện hiếm hoi. Nếu việc đổi tên phải xảy ra, việc tìm kiếm thay thế trong hai hệ thống không mất nhiều thời gian hơn một hệ thống. Nó vẫn gây ra ít thời gian chết và tình tiết tăng nặng hơn so với di chuyển DB. Tôi biết nó độc đáo, nhưng nó hoạt động rất tốt cho tôi :) – Paulo

2

Giải pháp tôi sử dụng (ban đầu được phát triển bởi một người bạn của tôi) là một phụ lục khác cho yukondude.

  1. Tạo thư mục lược đồ trong điều khiển phiên bản và sau đó cho mỗi thay đổi db, bạn giữ tệp .sql với SQL bạn muốn thực hiện cùng với truy vấn sql để cập nhật bảng db_schema.
  2. Tạo bảng cơ sở dữ liệu có tên "db_schema" với một cột số nguyên có tên là phiên bản.
  3. Trong thư mục lược đồ tạo hai kịch bản lệnh shell, "current" và "update".Việc thực thi hiện tại cho bạn biết phiên bản nào của lược đồ db mà cơ sở dữ liệu bạn đang kết nối hiện đang ở. Chạy cập nhật thực thi từng tệp .sql được đánh số lớn hơn phiên bản trong bảng db_schema tuần tự cho đến khi bạn lên đến tệp được đánh số lớn nhất trong thư mục lược đồ của bạn.

tập tin trong thư mục schema:

0-init.sql 
1-add-name-to-user.sql 
2-add-bio.sql 

Thật là một tập tin thông thường có vẻ như, lưu ý cập nhật db_schema ở phần cuối của mỗi tập tin sql:

BEGIN; 
-- comment about what this is doing 
ALTER TABLE user ADD COLUMN bio text NULL; 

UPDATE db_schema SET version = 2; 
COMMIT; 

Tập lệnh "hiện tại" (cho psql):

#!/bin/sh 

VERSION=`psql -q -t <<EOF 
\set ON_ERROR_STOP on 
SELECT version FROM db_schema; 
EOF 
` 

[ $? -eq 0 ] && { 
    echo $VERSION 
    exit 0 
} 

echo 0 

kịch bản cập nhật (cũng psql):

#!/bin/sh 

CURRENT=`./current` 
LATEST=`ls -vr *.sql |egrep -o "^[0-9]+" |head -n1` 

echo current is $CURRENT 
echo latest is $LATEST 

[[ $CURRENT -gt $LATEST ]] && { 
    echo That seems to be a problem. 
    exit 1 
} 

[[ $CURRENT -eq $LATEST ]] && exit 0 

#SCRIPT_SET="-q" 
SCRIPT_SET="" 

for ((I = $CURRENT + 1 ; I <= $LATEST ; I++)); do 
    SCRIPT=`ls $I-*.sql |head -n1` 
    echo "Adding '$SCRIPT'" 
    SCRIPT_SET="$SCRIPT_SET $SCRIPT" 
done 

echo "Applying updates..." 
echo $SCRIPT_SET 
for S in $SCRIPT_SET ; do 
    psql -v ON_ERROR_STOP=TRUE -f $S || { 
    echo FAIL 
    exit 1 
    } 
done 
echo OK 

My 0-init.sql có cấu trúc sơ đồ ban đầu đầy đủ cùng với ban đầu "UPDATE db_schema SET version = 0;". Không nên quá khó để sửa đổi các tập lệnh này cho MySQL. Trong trường hợp của tôi, tôi cũng có

export PGDATABASE="dbname" 
export PGUSER="mike" 

trong .bashrc của tôi. Và nó sẽ nhắc mật khẩu với mỗi tập tin đang được thực thi.

0

Trước đây tôi đã sử dụng LiquiBase, một công cụ dựa trên Java nơi bạn định cấu hình di chuyển của mình dưới dạng tệp XML. Bạn có thể tạo ra SQL cần thiết với nó.

Hôm nay tôi sẽ sử dụng thư viện Doctrine 2migration facilities tương tự như Ruby.

Khuôn khổ Symfony 2 cũng có cách tốt để xử lý các thay đổi lược đồ - công cụ dòng lệnh của nó có thể phân tích lược đồ hiện có và tạo SQL để khớp cơ sở dữ liệu với các định nghĩa lược đồ đã thay đổi.

+0

Thú vị, cảm ơn ... – Polsonby

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