Có thể chạy các ứng dụng Hibernate được cấu hình hbm2ddl.auto=update
để cập nhật lược đồ cơ sở dữ liệu trong môi trường sản xuất không?
Có thể chạy các ứng dụng Hibernate được cấu hình hbm2ddl.auto=update
để cập nhật lược đồ cơ sở dữ liệu trong môi trường sản xuất không?
Câu trả lời:
Không, nó không an toàn.
Bất chấp những nỗ lực tốt nhất của nhóm Hibernate, bạn chỉ đơn giản là không thể dựa vào các bản cập nhật tự động trong sản xuất . Viết các bản vá của riêng bạn, xem xét chúng với DBA, kiểm tra chúng, sau đó áp dụng chúng theo cách thủ công.
Về mặt lý thuyết, nếu cập nhật hbm2ddl hoạt động trong quá trình phát triển, thì nó cũng sẽ hoạt động trong sản xuất. Nhưng trong thực tế, không phải lúc nào cũng như vậy.
Ngay cả khi nó hoạt động tốt, nó có thể là tối ưu phụ. Các DBA được trả nhiều như vậy vì một lý do.
Chúng tôi thực hiện nó trong sản xuất mặc dù với một ứng dụng không phải là nhiệm vụ quan trọng và không có nhân viên DBA nào được trả lương cao. Đó chỉ là một quy trình thủ công ít hơn do lỗi của con người - ứng dụng có thể phát hiện sự khác biệt và thực hiện đúng, cộng với việc bạn có thể đã thử nghiệm nó trong các môi trường thử nghiệm và phát triển khác nhau.
Một cảnh báo - trong một môi trường nhóm, bạn có thể muốn tránh nó vì nhiều ứng dụng có thể xuất hiện cùng một lúc và cố gắng sửa đổi lược đồ có thể xấu. Hoặc đặt trong một số cơ chế trong đó chỉ có một phiên bản được phép cập nhật lược đồ.
Những người sáng tạo Hibernate không khuyến khích làm như vậy trong môi trường sản xuất trong cuốn sách "Sự kiên định của Java với Hibernate" :
CẢNH BÁO: Chúng tôi đã thấy người dùng Hibernate đang cố gắng sử dụng SchemaUpdate để tự động cập nhật lược đồ của cơ sở dữ liệu sản xuất. Điều này có thể nhanh chóng kết thúc trong thảm họa và sẽ không được DBA của bạn cho phép.
Kiểm tra LiquiBase XML để giữ thay đổi cập nhật. Tôi chưa bao giờ sử dụng nó cho đến năm nay, nhưng tôi thấy rằng nó rất dễ học và làm cho việc kiểm soát / di chuyển / quản lý thay đổi DB trở nên rất dễ dàng. Tôi làm việc trong dự án Groovy / Grails và Grails sử dụng Hibernate bên dưới cho tất cả ORM của nó (được gọi là "GORM"). Chúng tôi sử dụng Liquibase để quản lý tất cả các thay đổi lược đồ SQL, điều mà chúng tôi thực hiện khá thường xuyên khi ứng dụng của chúng tôi phát triển với các tính năng mới.
Về cơ bản, bạn giữ một tệp XML các thay đổi mà bạn tiếp tục thêm vào khi ứng dụng của bạn phát triển. Tập tin này được giữ trong git (hoặc bất cứ điều gì bạn đang sử dụng) với phần còn lại của dự án của bạn. Khi ứng dụng của bạn được triển khai, Liquibase sẽ kiểm tra bảng thay đổi của nó trong DB mà bạn đang kết nối để nó sẽ biết những gì đã được áp dụng, sau đó nó sẽ áp dụng một cách thông minh bất kỳ thay đổi nào chưa được áp dụng từ tệp. Nó hoạt động hoàn toàn tuyệt vời trong thực tế và nếu bạn sử dụng nó cho tất cả các thay đổi lược đồ của mình, thì bạn có thể tin tưởng 100% rằng mã bạn kiểm tra và triển khai sẽ luôn có thể kết nối với một lược đồ cơ sở dữ liệu tương thích hoàn toàn.
Điều tuyệt vời là tôi có thể lấy một cơ sở dữ liệu mysql hoàn toàn trống trên máy tính xách tay của mình, kích hoạt ứng dụng và ngay lập tức lược đồ được thiết lập cho tôi. Nó cũng giúp dễ dàng kiểm tra các thay đổi lược đồ bằng cách áp dụng các thay đổi này cho db cục bộ hoặc phân tầng db trước.
Cách dễ nhất để bắt đầu với nó có lẽ là lấy DB hiện tại của bạn và sau đó sử dụng Liquibase để tạo tệp baseline.xml ban đầu. Sau đó, trong tương lai, bạn có thể thêm vào nó và để cho Liquidibase tiếp quản việc thay đổi lược đồ.
hbm2ddl.auto=update
để ánh xạ Class / DB của bạn được xác thực và bạn có toàn quyền kiểm soát việc tạo DB thông qua chất lỏng. Bạn nghĩ sao?
validate
Tôi sẽ bỏ phiếu không. Hibernate dường như không hiểu khi kiểu dữ liệu cho các cột đã thay đổi. Ví dụ (sử dụng MySQL):
String with @Column(length=50) ==> varchar(50)
changed to
String with @Column(length=100) ==> still varchar(50), not changed to varchar(100)
@Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed
Có lẽ có nhiều ví dụ khác, chẳng hạn như đẩy độ dài của cột Chuỗi lên hơn 255 và thấy nó chuyển đổi thành văn bản, văn bản trung bình, v.v.
Cấp, tôi không nghĩ rằng thực sự có một cách để "chuyển đổi kiểu dữ liệu" mà không cần tạo cột mới, sao chép dữ liệu và thổi bay cột cũ. Nhưng phút mà cơ sở dữ liệu của bạn có các cột không phản ánh ánh xạ Hibernate hiện tại mà bạn đang sống rất nguy hiểm ...
Flyway là một lựa chọn tốt để giải quyết vấn đề này:
@Column(length = 45)
thành @Column(length = 255)
. Có thể xác minh rằng Hibernate 4.3.6.Final đã cập nhật chính xác lược đồ cơ sở dữ liệu bằng cách sử dụng hbm2ddl.auto=update
. (Một điều cần đề cập đến là cơ sở dữ liệu hiện không có bất kỳ dữ liệu trong nó -. Chỉ cấu trúc)
Hibernate đã đưa khuyến cáo về việc không sử dụng cập nhật tự động trong sản để trang trải bản thân khi những người không biết những gì họ đang làm sử dụng nó trong những tình huống mà nó không nên được sử dụng.
Đã cấp các tình huống không nên sử dụng nhiều hơn các tình huống mà nó ổn.
Tôi đã sử dụng nó trong nhiều năm cho nhiều dự án khác nhau và chưa bao giờ có một vấn đề nào. Đó không phải là một câu trả lời khập khiễng, và nó không phải là mã hóa cao bồi. Đó là một sự thật lịch sử.
Một người nói rằng "không bao giờ làm điều đó trong sản xuất" đang nghĩ đến một tập hợp triển khai sản xuất cụ thể, cụ thể là những công việc mà anh ta quen thuộc (công ty của anh ta, ngành công nghiệp của anh ta, v.v.).
Vũ trụ của "triển khai sản xuất" là rất lớn và đa dạng.
Một nhà phát triển Hibernate có kinh nghiệm biết chính xác DDL sẽ ra sao từ một cấu hình ánh xạ nhất định. Miễn là bạn kiểm tra và xác nhận rằng những gì bạn mong đợi kết thúc trong DDL (theo dev, qa, staging, v.v.), bạn vẫn ổn.
Khi bạn thêm nhiều tính năng, cập nhật lược đồ tự động có thể là một trình tiết kiệm thời gian thực.
Danh sách các nội dung cập nhật tự động sẽ không xử lý là vô tận, nhưng một số ví dụ là di chuyển dữ liệu, thêm các cột không thể rỗng, thay đổi tên cột, v.v.
Ngoài ra, bạn cần phải chăm sóc trong môi trường cụm.
Nhưng một lần nữa, nếu bạn biết tất cả những thứ này, bạn sẽ không hỏi câu hỏi này. Hừm. . . OK, nếu bạn đang hỏi câu hỏi này, bạn nên đợi cho đến khi bạn có nhiều kinh nghiệm với các bản cập nhật lược đồ tự động và Hibernate trước khi bạn nghĩ về việc sử dụng nó trong prod.
Như tôi đã giải thích trong bài viết này , nó không phải là một ý tưởng tốt để sử dụng hbm2ddl.auto
trong sản xuất.
Cách duy nhất để quản lý lược đồ cơ sở dữ liệu là sử dụng các tập lệnh di chuyển gia tăng bởi vì:
Ngay cả Hướng dẫn sử dụng Hibernate cũng khuyên bạn tránh sử dụng hbm2ddl
công cụ cho môi trường sản xuất.
SchemaExport
như thể hiện bởi trường hợp thử nghiệm này .
Chúng tôi làm điều đó trong một dự án đang chạy trong sản xuất trong nhiều tháng nay và chưa bao giờ có vấn đề gì cho đến nay. Hãy ghi nhớ 2 thành phần cần thiết cho công thức này:
Thiết kế mô hình đối tượng của bạn với cách tiếp cận tương thích ngược, đó là phản đối các đối tượng và thuộc tính thay vì loại bỏ / thay đổi chúng. Điều này có nghĩa là nếu bạn cần thay đổi tên của một đối tượng hoặc thuộc tính, hãy để nguyên cái cũ, thêm cái mới và viết một số loại kịch bản di chuyển. Nếu bạn cần thay đổi liên kết giữa các đối tượng, nếu bạn đã sản xuất, điều này có nghĩa là thiết kế của bạn đã sai ngay từ đầu, vì vậy hãy thử nghĩ ra một cách mới để thể hiện mối quan hệ mới, mà không ảnh hưởng đến dữ liệu cũ.
Luôn sao lưu cơ sở dữ liệu trước khi triển khai.
Ý thức của tôi là - sau khi đọc bài đăng này - rằng 90% những người tham gia vào cuộc thảo luận này đều kinh hoàng chỉ với suy nghĩ sử dụng tự động hóa như thế này trong môi trường sản xuất. Một số ném bóng vào DBA. Hãy dành một chút thời gian để xem xét rằng không phải tất cả các môi trường sản xuất sẽ cung cấp một DBA và không có nhiều nhóm phát triển có thể đủ khả năng chi trả (ít nhất là cho các dự án cỡ trung bình). Vì vậy, nếu chúng ta đang nói về các đội mà mọi người phải làm mọi thứ, quả bóng sẽ ở trên họ.
Trong trường hợp này, tại sao không cố gắng để có tốt nhất của cả hai thế giới? Các công cụ như thế này có mặt để giúp đỡ, với thiết kế và kế hoạch cẩn thận - có thể giúp ích trong nhiều tình huống. Và tin tôi đi, ban đầu các quản trị viên có thể khó thuyết phục nhưng nếu họ biết rằng quả bóng không nằm trong tay họ, họ sẽ thích nó.
Cá nhân, tôi sẽ không bao giờ quay lại viết kịch bản bằng tay để mở rộng bất kỳ loại lược đồ nào, nhưng đó chỉ là ý kiến của tôi. Và sau khi bắt đầu áp dụng cơ sở dữ liệu không có lược đồ NoQuery gần đây, tôi có thể thấy rằng sớm thôi, tất cả các hoạt động dựa trên lược đồ này sẽ thuộc về quá khứ, vì vậy bạn nên bắt đầu thay đổi quan điểm của mình và nhìn về phía trước.
Tôi sẽ không mạo hiểm vì cuối cùng bạn có thể mất dữ liệu cần được bảo tồn. hbm2ddl.auto = update hoàn toàn là một cách dễ dàng để giữ cho cơ sở dữ liệu dev của bạn được cập nhật.
Trong trường hợp của tôi (Hibernate 3.5.2, Postgresql, Ubuntu), cài đặt hibernate.hbm2ddl.auto=update
chỉ tạo các bảng mới và tạo các cột mới trong các bảng đã có sẵn.
Nó không bỏ bảng, cũng không thả cột, cũng không thay đổi cột. Nó có thể được gọi là một lựa chọn an toàn, nhưng một cái gì đó như hibernate.hbm2ddl.auto=create_tables add_columns
sẽ rõ ràng hơn.
Nó không an toàn, không được khuyến khích, nhưng nó có thể.
Tôi có kinh nghiệm trong một ứng dụng sử dụng tùy chọn tự động cập nhật trong sản xuất.
Vâng, các vấn đề và rủi ro chính được tìm thấy trong giải pháp này là:
Vì vậy, tôi sẽ không khuyến nghị sử dụng tự động cập nhật trong sản xuất.
Nếu bạn thực sự muốn sử dụng tự động cập nhật trong sản xuất, tôi khuyên bạn nên:
Và, khác với các bài đăng khác, tôi không nghĩ rằng cập nhật tự động cho phép nó liên quan đến các DBA "được trả lương rất cao" (như đã đề cập trong các bài đăng khác). Các DBA có nhiều việc quan trọng hơn là viết các câu lệnh SQL để tạo / thay đổi / xóa các bảng và cột. Các tác vụ đơn giản hàng ngày này có thể được các nhà phát triển thực hiện và tự động hóa và chỉ được thông qua để nhóm DBA xem xét, không cần Hibernate và các DBA "được trả lương rất cao" để viết chúng.
Thông thường các ứng dụng doanh nghiệp trong các tổ chức lớn chạy với các đặc quyền giảm.
Tên người dùng cơ sở dữ liệu có thể không có DDL
đặc quyền để thêm các cột hbm2ddl.auto=update
yêu cầu.
Tôi đồng ý với Vladimir. Các quản trị viên trong công ty của tôi chắc chắn sẽ không đánh giá cao nếu tôi thậm chí còn đề xuất một khóa học như vậy.
Hơn nữa, việc tạo tập lệnh SQL thay vì tin tưởng mù quáng Hibernate cho bạn cơ hội xóa các trường không còn được sử dụng. Hibernate không làm điều đó.
Và tôi thấy việc so sánh lược đồ sản xuất với lược đồ mới mang đến cho bạn cái nhìn sâu sắc hơn nữa về wat mà bạn đã thay đổi trong mô hình dữ liệu. Bạn biết, tất nhiên, bởi vì bạn đã thực hiện nó, nhưng bây giờ bạn thấy tất cả những thay đổi trong một lần. Ngay cả những thứ khiến bạn phải thốt lên như "Cái quái gì vậy?!".
Có những công cụ có thể tạo một lược đồ delta cho bạn, vì vậy nó thậm chí không khó. Và sau đó bạn biết chính xác những gì sẽ xảy ra.
Lược đồ của ứng dụng có thể phát triển theo thời gian; nếu bạn có một số cài đặt, có thể ở các phiên bản khác nhau, bạn nên có một số cách để đảm bảo rằng ứng dụng của bạn, một loại công cụ hoặc tập lệnh nào đó có khả năng di chuyển lược đồ và dữ liệu từ một phiên bản sang từng phiên bản sau.
Có tất cả sự kiên trì của bạn trong ánh xạ Hibernate (hoặc chú thích) là một cách rất tốt để kiểm soát sự tiến hóa của lược đồ.
Bạn nên xem xét rằng tiến hóa lược đồ có một số khía cạnh cần được xem xét:
sự phát triển của lược đồ cơ sở dữ liệu trong việc thêm nhiều cột và bảng
bỏ cột cũ, bảng và quan hệ
điền vào các cột mới với mặc định
Các công cụ ngủ đông rất quan trọng trong trường hợp cụ thể (như theo kinh nghiệm của tôi), bạn có các phiên bản khác nhau của cùng một ứng dụng trên nhiều loại cơ sở dữ liệu khác nhau.
Điểm 3 rất nhạy cảm trong trường hợp bạn đang sử dụng Hibernate, như trong trường hợp bạn giới thiệu một thuộc tính hoặc giá trị boolean mới, nếu Hibernate sẽ tìm thấy bất kỳ giá trị null nào trong các cột như vậy, nếu sẽ đưa ra một ngoại lệ.
Vì vậy, những gì tôi sẽ làm là: thực sự sử dụng khả năng cập nhật lược đồ của công cụ Hibernate, nhưng bạn phải thêm vào đó một số cuộc gọi lại bảo trì lược đồ, như để điền mặc định, bỏ các cột không còn sử dụng và tương tự. Theo cách này, bạn có được những lợi thế (tập lệnh cập nhật lược đồ độc lập cơ sở dữ liệu và tránh mã hóa trùng lặp các bản cập nhật, theo sự kiên trì và trong tập lệnh) nhưng bạn cũng bao quát tất cả các khía cạnh của hoạt động.
Vì vậy, ví dụ, nếu một bản cập nhật phiên bản chỉ đơn giản là thêm một thuộc tính có giá trị varchar (do đó là cột), có thể mặc định là null, với bản cập nhật tự động, bạn sẽ hoàn thành. Trường hợp phức tạp hơn là cần thiết, sẽ cần nhiều công việc hơn.
Điều này giả định rằng ứng dụng khi được cập nhật có khả năng cập nhật lược đồ của nó (có thể được thực hiện), điều đó cũng có nghĩa là nó phải có quyền người dùng để làm như vậy trên lược đồ. Nếu chính sách của khách hàng ngăn chặn điều này (có thể là trường hợp Lizard Brain), bạn sẽ phải cung cấp cơ sở dữ liệu - các tập lệnh cụ thể.