Di chuyển một ứng dụng PHP từ MySQL sang DB2, Phần 3: Chuyển đổi mã PHP của bạn

Các bài học từ một nghiên cứu chi tiết về một ứng dụng mạng nội bộ của IBM

Tìm hiểu tại sao cần di chuyển một ứng dụng PHP sang DB2®, cách lập kế hoạch di trú, cách thực hiện nó, cách hỗ trợ nó và cách xử lý các rủi ro tiềm năng dựa trên kinh nghiệm của một nghiên cứu chi tiết về ứng dụng mạng nội bộ của IBM. Loạt bài bốn phần này chia sẻ các bài học từ một cuộc di trú MySQL-sang-DB2 thành công cho một ứng dụng mạng nội bộ PHP trọng yếu được 4.000 người dùng toàn cầu trong IBM sử dụng để hỗ trợ sản xuất nội dung cho ibm.com. Phần 3 mô tả các bước cần thực hiện để chuyển đổi mã PHP.

Daniel Krook, Kỹ sư phần mềm, IBM

Daniel Krook là một chuyên gia CNTT có chứng chỉ xuất sắc của IBM/Open Group làm việc tại vùng New York City mở rộng. Ông đã có hơn mười năm kinh nghiệm trong việc phát triển ứng dụng web và hiện đang xây dựng một cơ sở hạ tầng Đám mây cho IBM bằng cách sử dụng các công nghệ Java EE, DB2, REST và công nghệ di động. Ông có các chứng chỉ về PHP, Java EE, BlackBerry, DB2 và Solaris. Ông viết các bài liên quan đến PHP cho developerWorks của IBM và đồng tác giả của quyển sách IBM Redbook "Developing PHP Applications for IBM Data Servers (Phát triển các ứng dụng PHP cho Các máy chủ dữ liệu của IBM)".


Cấp độ đóng góp cho developerWorks của
        tác giả

Yan Li Mu, Kiến trúc sư CNTT, IBM

Yan Li Mu là một kiến trúc sư công nghệ thông tin làm việc tại Đại Liên, Trung Quốc. Ông có hơn tám năm kinh nghiệm về phát triển ứng dụng web tập trung vào các công nghệ Java EE, PHP và phát triển cơ sở dữ liệu



Mark Nusekabel, Kiến trúc sư CNTT cao cấp, I.B.M.

Mark Nusekabel là một Kiến trúc sư CNTT có chứng chỉ xuất sắc của IBM/Open Group sống ở vịnh Tampa, vùng Florida. Ông đã có hơn 20 năm kinh nghiệm trong lĩnh vực công nghệ thông tin và ông hiện đang xây dựng các công cụ nội bộ bằng cách sử dụng JavaScript, PHP, Java và DB2. Ông có các chứng chỉ về các giải pháp kinh doanh điện tử, Java và XML.



14 02 2012

Giới thiệu về loạt bài này

MySQL hiện là máy chủ cơ sở dữ liệu phổ biến nhất được sử dụng với ngôn ngữ lập trình PHP để xây dựng các ứng dụng web động. Tuy nhiên, DB2 là một cơ sở dữ liệu phổ biến khác được PHP hỗ trợ đầy đủ và cung cấp các lợi thế hấp dẫn hơn so với MySQL, làm cho nó trở thành một sự lựa chọn lý tưởng cho nhiều ứng dụng.

Loạt bài này mô tả tại sao việc di chuyển một ứng dụng PHP sang DB2 lại có ý nghĩa, cách chuẩn bị cho việc di trú, cách thực hiện nó, cách hỗ trợ nó, và cách xử lý các rủi ro tiềm năng dựa trên kinh nghiệm của các tác giả cho một cuộc di trú mới nhất. Nhiều mẫu mã và mẫu cấu hình được cung cấp, cũng như các chỉ dẫn tài nguyên để giúp cho dự án chạy trơn tru.

Với các ví dụ và các bài học thu được từ một việc chuyển đổi thực tế thành công, bạn sẽ thấy đây có thể là một dự án đơn giản, có đủ tài liệu và cung cấp các lợi ích hấp dẫn.

Loạt bài bốn phần này chia sẻ các bài học nhận được từ cuộc di trú MySQL-sang-DB2 thành công cho một ứng dụng mạng nội bộ PHP trọng yếu, cấp độ sản xuất, được 4.000 người dùng toàn cầu trong IBM sử dụng để hỗ trợ sản xuất nội dung cho ibm.com.

  • Phần 1 mô tả các bước cần thực hiện để chuẩn bị cho việc di trú.
  • Phần 2 mô tả các bước cần thực hiện để di trú cơ sở dữ liệu.
  • Phần 3 mô tả các bước cần thực hiện để chuyển đổi mã PHP.
  • Phần 4 mô tả các bước cần thực hiện để triển khai và hỗ trợ ứng dụng.

Bạn sẽ học được những gì

Mục đích của loạt bài này là cho bạn hiểu những gì thường cần thiết để di trú một ứng dụng PHP từ MySQL sang DB2, những tài nguyên nào có sẵn để trợ giúp bạn và một nhóm dự án của IBM đã thực hiện nhiệm vụ này vào đầu năm 2010 như thế nào.

Nếu bạn đã nghiên cứu một cuộc di trú từ MySQL sang DB2, bạn có thể đã thấy những giá trị mà DB2 cung cấp dựa trên tài liệu sản phẩm, các đánh giá tiêu chuẩn về hiệu năng, các tính năng mà bạn đã đọc trong tài liệu DB2, hoặc các so sánh trong các Sách Đỏ của IBM (IBM Redbooks ®) dành riêng cho nhiệm vụ này, bao gồm cuốn Hướng dẫn chuyển đổi MySQL sang DB2 (xem phần Tài nguyên ).

Bạn có lẽ cũng biết rằng DB2 Express-C là một máy chủ dữ liệu quan hệ có đủ chức năng, miễn phí có thể dễ dàng được cài đặt hoặc được đánh giá bằng cách sử dụng IBM SmartCloud (tên cũ là Development and Test on the Cloud - Phát triển và Thử nghiệm trên Đám mây của IBM) hoặc Amazon EC2. Các liên kết đến các tài nguyên này có sẵn trong phần Tài nguyên.

Loạt bài này cung cấp cho bạn một ví dụ cụ thể về cuộc di trú thực tế đã được thực hiện thành công như thế nào trong năm 2010 cho một ứng dụng mạng nội bộ PHP được sử dụng rất nhiều trong IBM để hỗ trợ quản lý nội dung hàng ngày được công bố trên nhiều phần của trang Web ibm.com.

Sau khi bạn đọc xong loạt bài này, bạn sẽ có thể tạo một trường hợp di trú tương tự, hiểu được thời hạn và các phụ thuộc của các mục công việc cần được thực hiện, dự kiến các rủi ro tiềm năng, và biết nơi để tìm kiếm sự hỗ trợ từng bước trên đường đi. Tất cả điều này sẽ cho bạn sự tự tin hơn để lựa chọn DB2 và sử dụng nó một cách tốt nhất cho các ứng dụng PHP của bạn hiện đang được phát triển trên MySQL.

Những gì không trình bày

Loạt bài này nhằm chia sẻ các bài học thu được từ một cuộc di trú nội bộ IBM từ MySQL sang DB2 và cung cấp cho bạn thông tin về tài nguyên có sẵn để thực hiện một công cuộc tương tự. Loạt bài này không phải là một hướng dẫn toàn diện về di trú để có thể áp dụng được cho tất cả các kịch bản.

Để xác định một cách tiếp cận phù hợp với bạn, hãy tham khảo Hướng dẫn chuyển đổi MySQL sang DB2 hoặc liên hệ với SMPO (Software Migration Project Office - Văn phòng dự án di trú phần mềm) để đánh giá di trú miễn phí. Các liên kết này được cung cấp trong phần Tài nguyên.


Giới thiệu về việc di trú mã

Bài này trình bày năm bước làm việc chính trong một nghiên cứu chi tiết để thực hiện di trú mã ứng dụng PHP từ chỗ đang sử dụng các trình điều khiển và cú pháp MySQL tới chỗ làm việc với DB2. Nếu cần, hãy tham khảo Phần 1 của loạt bài này để xem lịch trình các bước ấy trong quá trình di trú tổng thể trước khi tiến hành chuyển đổi.

Bước 1: Bắt đầu bước chuyển đầu tiên trong di trú mã
  • Đảm bảo cập nhật cấu hình PHP để hỗ trợ DB2.
  • Cập nhật các câu lệnh SQL riêng lẻ để hỗ trợ cú pháp DB2.
  • Mô phỏng các hàm MySQL nguyên gốc bằng cách sử dụng các hàm DB2 do người dùng định nghĩa, nếu cần.
  • Di chuyển logic xử lý từ SQL vào PHP, nếu cần.
Bước 2: Bắt đầu bước chuyển thứ hai trong di trú mã
  • Xem xét các thay đổi cần thiết để hỗ trợ các mức cách ly thích hợp.
  • Tổ chức lại các truy vấn thành các đơn vị công việc logic để đạt được tính toàn vẹn dữ liệu tốt hơn và cải thiện hiệu năng.
Bước 3: Bắt đầu thử nghiệm trường hợp sử dụng nghiệp vụ khởi đầu với các bên liên quan
  • Phối hợp các bên liên quan để thực hiện các trường hợp sử dụng đã quen thực hiện trong hệ thống cũ.
  • Nắm bắt các thất bại kiểm thử như là các khiếm khuyết cần được các nhà phát triển phân tích và sửa chữa.
Bước 4: Giải quyết nút nghẽn cổ chai và xác nhận dựa vào vạch chuẩn chức năng
  • Cải thiện hiệu năng của hệ thống dựa vào sự phản hồi của người dùng sau khi kiểm tra chức năng.
  • Tập trung vào những gì DB2 có thể sửa chữa tự động cho bạn, vì DB2 là sự thay đổi lớn nhất mà bạn đưa vào.
  • Giải quyết nút nghẽn cổ chai PHP bằng cách xem xét cách sử dụng tài nguyên của hệ điều hành.
Bước 5: Đánh giá vạch chuẩn di trú mã
  • Sau khi hoàn thành theo cách lặp lại các bước trên, khai báo hoàn thành việc chuyển đổi mã.
  • Sao lưu hệ thống và gắn thẻ mốc quan trọng trong hệ thống kiểm soát mã nguồn của bạn.
  • Đánh giá mức độ chuẩn bị cần thiết cho nhiệm vụ tiếp theo: triển khai ứng dụng.

Tìm hiểu nghiên cứu chi tiết về ví dụ cơ sở mã PHP của PTT hiện có

Nhắc nhở

Nếu cần, hãy tự mình tìm hiểu phần Tài nguyên có thể giúp ích trong việc di trú của bạn. Các tài nguyên sau có thể đặc biệt có ích cho bước này:

  • Chương 8 và 10 trong Sách Đỏ miễn phí của IBM (IBM Redbook ®) Hướng dẫn chuyển đổi MySQL sang DB2.
  • Chương 4 và 6 trong Sách Đỏ miễn phí của IBM Phát triển các ứng dụng PHP cho Các máy chủ dữ liệu IBM.
  • Bài viết trên developerWorks "Danh sách khuyến khích đọc: Phát triển ứng dụng DB2 cho Linux, UNIX, và Windows".
  • Các mục blog của Daniel Krook về kinh nghiệm cá nhân của ông trong một dự án di trú cho một ISV.

Tất nhiên các tài liệu về ngôn ngữ lập trình PHP và phần mở rộng của trình điều khiển DB2 cũng là các phương tiện cần thiết.

Một lựa chọn khác là sử dụng đám mây cho quá trình di trú. Bạn có thể sử dụng Linux EC2 của Amazon và các AMI của DB2, hoặc đăng ký dùng IBM SmartCloud (tên cũ là Development and Test on the Cloud - Phát triển và Thử nghiệm trên Đám mây của IBM)(xem phần Tài nguyên ).

Với ứng dụng ví dụ trong bài này, mã nguồn cho Project Tracking Tool (PTT - Công cụ theo dõi dự án) bao gồm hàng trăm tệp PHP. Cơ sở mã có các thư viện hàm, mã hướng-đối tượng được tổ chức thành các đối tượng truyền dữ liệu và các lớp của trình quản lý, các đoạn khuôn mẫu HTML khác nhau và các trình trợ giúp để biểu hiện giao diện người dùng.

Cơ sở dữ liệu PTT được sử dụng với các hàm khác nhau để hỗ trợ luồng công việc cung cấp thông tin được công bố trên ibm.com. Hơn 4.000 người dùng trên toàn thế giới truy cập và sửa đổi cơ sở dữ liệu PTT thông qua mặt tiền web PHP. Tại bất kỳ thời điểm nào, đều có hàng trăm người dùng đang hoạt động đồng thời trên hệ thống.

Mã này được triển khai vào một máy chủ web Apache, nó nạp tệp mod_php như là một mô đun chia sẻ.

Trong ví dụ này, mã hiện có đã được cập nhật cho hệ thống DB2 mới, chủ yếu là bằng cách thực hiện các sửa đổi với SQL nhúng. Các sửa đổi nhỏ khác bắt buộc phải làm là cập nhật cấu hình PHP để sử dụng trình điều khiển DB2 và điều chỉnh mã kết nối cơ sở dữ liệu, sử dụng một chuỗi kết nối mới. Bài này cũng xác định và tập trung vào một số cải tiến cấu trúc ứng dụng để hoàn thiện hơn khung kiến trúc mô hình-khung nhìn-trình điều khiển (MVC) nhằm cải tiến chất lượng, tổ chức và bảo trì ứng dụng.


Cài đặt phần mềm chuyển đổi

Để chuẩn bị cho việc chuyển đổi mã ví dụ, hãy cài đặt các thành phần sau đây trên một máy trạm Windows được sử dụng để thực hiện các bước chuyển đổi.

Một phiên bản của bản sao MySQL của cơ sở dữ liệu nguồn
Để kiểm tra mỗi thay đổi mã, điều quan trọng là có một bản sao của hệ thống cũ sẵn sàng để sử dụng làm một tham chiếu chức năng để xác nhận hợp lệ các thay đổi cho hệ thống mới bên cạnh hệ thống cũ. Bạn có thể sử dụng chính hệ thống như bạn đã làm trong Phần 2.
Một phiên bản DB2 với các trình điều khiển máy chủ dữ liệu được cài đặt cục bộ hoặc trên một máy chủ thử nghiệm
Cài đặt DB2 để tạo cơ sở dữ liệu đích mới trên máy trạm. Nói chung, cơ sở dữ liệu này không nhất thiết là ấn bản giống như cơ sở dữ liệu được sử dụng trong sản xuất, nhưng để tương thích tính năng hoàn toàn, một ý tưởng tốt là nên chọn cùng ấn bản. Để làm theo các ví dụ trong bài này, hãy cài đặt Ấn bản máy chủ doanh nghiệp của DB2 (DB2 Enterprise Server Edition) Phiên bản 9.7.2. Đảm bảo rằng các trình điều khiển của máy chủ dữ liệu có sẵn để cung cấp các thư viện khách PHP cần thiết. Bạn có thể sử dụng chính hệ thống như bạn đã làm trong Phần 2.
Một phiên bản PHP được xây dựng với phần mở rộng ibm_db2 hoặc PDO_IBM (PHP Data Objects)
Tải về phiên bản mới nhất của Zend Server và chọn phần mở rộng DB2 tùy chọn, có yêu cầu cài đặt các gói bổ sung.
Một môi trường phát triển tích hợp (IDE), ví dụ Zend Studio hoặc Các công cụ phát triển PHP (PDT) của Eclipse
Sử dụng một IDE nhận biết-PHP, ví dụ Zend Studio hoặc Các công cụ phát triển PHP của Eclipse, để dễ dàng phát triển PHP của bạn. Vì bạn duy trì một ứng dụng PHP, nên nhiều khả năng là bạn đã có một công cụ ưa thích.

Hãy chắc chắn ghi lại chi tiết các quyết định cấu hình và các bài học thu được của bạn để cho bạn có thể lặp lại các bước khi triển khai. Xem xét việc ghi lưu một ảnh chụp của hệ điều hành Windows thành một ảnh ảo tại các cột mốc chính mỗi khi đạt được các đích quan trọng để dùng làm các bản sao lưu cấu hình và các vạch chuẩn để so sánh cải thiện tiếp mã lệnh.

Nếu bạn muốn chụp một ảnh của một cấu hình máy tính vật lý, bạn có thể làm điều đó bằng VMware vCenter Converter miễn phí. Một cách thay thế khác là xem xét dùng đám mây cho các thay đổi năng động này. Bạn có thể sử dụng các AMI DB2 cho EC2 của Amazon, hoặc bạn có thể đăng ký dùng IBM SmartCloud (tên cũ là Development and Test on the IBM Cloud). Với các máy tính ảo, bạn sẽ có thể tránh được các cố gắng ban đầu để mua phần cứng máy chủ và cài đặt một hệ điều hành và DB2, điều này sẽ tiết kiệm thời gian, tăng tốc độ di trú, và mang lại cho bạn sự tự tin để trải nghiệm với cấu hình phù hợp nhất cho các nhu cầu của bạn. Có thể tìm thấy các liên kết đến tất cả các sản phẩm này trong phần Tài nguyên.


Bước 1: Bắt đầu một bước chuyển đầu tiên về di trú mã

Bước chuyển đổi mã quan trọng đầu tiên là cấu hình cơ sở hạ tầng PHP và DB2 mới và chuyển đổi cách ứng dụng sử dụng PHP và SQL để truy cập dữ liệu. Bước này liên quan đến các bước nhỏ sau:

Cập nhật cấu hình và trình điều khiển PHP

Đảm bảo rằng cấu hình PHP hiện có được sửa đổi để hỗ trợ trình điều khiển của DB2, để khớp với bộ mã hóa ký tự cơ sở dữ liệu máy chủ và để cung cấp các thông báo chẩn đoán quan trọng thông qua cảnh báo và các thông báo lỗi đầy đủ mọi chi tiết.

Để cập nhật mã PHP cho DB2, bạn sẽ thường thay đổi từng điểm trong mã ở đó các hàm mở rộng ibm_db2 được sử dụng hoặc cập nhật chuỗi kết nối PDO_IBM để thực hiện giao diện PDO (Các đối tượng dữ liệu PHP). Nếu bạn sử dụng PDO như một thư viện trừu tượng hóa cơ sở dữ liệu trong hệ thống dựa trên MySQL của mình, các thay đổi mã của bạn sẽ không đáng kể. Đó chỉ là vấn đề thay đổi một chuỗi kết nối duy nhất. Nhưng cho dù là bạn đang sử dụng phần mở rộng thủ tục ibm_db2, nhiệm vụ này cũng đơn giản. Bạn có thể thay thế bình thường bất kỳ các hàm nào bắt đầu với mysql_ hoặc mysqli_ trong mã của bạn bằng các tiền tố db2_ tương đương. Xem phần 6.3 Chương 6 về Phát triển các ứng dụng PHP cho các máy chủ dữ liệu của IBM trong Sách Đỏ của IBM (xem phần Tài nguyên) để biết các bảng ánh xạ tương ứng các hàm và mã mẫu.

Cả hai phương thức kết nối đều dựa vào máy khách DB2 làm một cầu nối để nối đến máy chủ DB2, vì vậy bạn cần xác nhận rằng máy khách DB2 đã được cấu hình khớp với các thiết lập trên máy chủ từ xa. Cụ thể, bạn cần đảm bảo chắc chắn rằng trang mã ký tự của máy khách DB2 giống như trang mã ký tự của máy chủ DB2, nếu không, bạn sẽ gặp khó khăn với các bộ ký tự. Với ví dụ này, hãy chạy lệnh được hiển thị trong Liệt kê 1 để thiết lập bộ mã hóa ký tự máy khách là UTF-8, sẽ phù hợp với lệnh CREATE DATABASE trong Liệt kê 1 trong Phần 2.

Liệt kê 1. Thiết lập trang mã máy khách DB2 thành UTF-8
db2set db2codepage=1208

Để đảm bảo thiết lập này được sử dụng trên mỗi máy trạm hoặc các máy chủ mà bạn cài đặt máy khách thời gian chạy, hãy chạy lệnh trong Liệt kê 2.

Liệt kê 2. Xem các biến cấu hình của DB2
db2set -all

Cuối cùng, trong quá trình phát triển, sẽ rất có ích nếu đảm bảo rằng tất cả các thông báo và các cảnh báo lỗi được thu giữ và được hiển thị trong trình duyệt. Trong tệp php.ini của bạn, hãy cập nhật các tham số được hiển thị trong Liệt kê 3. Hãy nhớ đặt chúng trở lại các thiết lập ít dài dòng hơn khi bạn chuyển sang sản xuất. Phần 4 của loạt bài này cung cấp một ví dụ về một cơ chế báo cáo lỗi thích hợp hơn để sử dụng khi bạn triển khai vào sản xuất.

Liệt kê 3. Thiết lập các tham số kiểm soát lỗi trong php.ini
display_errors = On
error_reporting = E_ALL & ~E_NOTICE

Chuyển đổi cú pháp SQL

Tiếp theo, hãy cập nhật các câu lệnh SQL riêng lẻ để hỗ trợ cú pháp DB2 hoặc thay đổi chúng để truy cập dữ liệu theo cách hơi khác một chút để đạt được kết quả tương tự. Đối với hầu hết các ứng dụng, bước này cần rất nhiều lần cập nhật mã và kiểm tra thử nghiệm. Tham khảo Chương 8.1 các điểm giống nhau và khác nhau của Ngôn ngữ thao tác dữ liệu trong Sách Đỏ Hướng dẫn chuyển đổi MySQL sang DB2 để xem một danh sách các phép chuyển đổi cú pháp phổ biến. Sau đây là một vài tình huống trong ứng dụng nghiên cứu chi tiết.

Cách xử lý ký tự đại diện của mệnh đề SELECT
Các câu lệnh SELECT sử dụng một ký tự đại diện (ký tự dấu hoa thị) để chọn cột cụ thể bên cạnh tất cả các cột của nhiều bảng là hợp pháp trong MySQL, nhưng chúng lại không được phép trong DB2. Trong trường hợp này, thêm tên bảng (hoặc bí danh) đầy đủ vào trước ký tự đại diện, chỉ rõ mỗi cột của mỗi bảng mà bạn đang quan tâm đến hoặc đơn giản là liệt kê tất cả các cột trong mỗi bảng với một ký tự đại diện duy nhất. Liệt kê 4 cho thấy cách sửa đổi các truy vấn như vậy.
Liệt kê 4. So sánh các ký tự đại diện của cột và bảng hợp pháp trong MySQL và DB2
-- In MySQL: 
SELECT R.NAME, * 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID;

-- In DB2: 
SELECT R.NAME, U.* 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID;

-- Or
SELECT R.NAME, U.ID, U.NAME, U.ROLE_ID, U.DEPART_ID 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID;
Mệnh đề SELECT quy định cụ thể kích thước tối đa của tập kết quả với LIMIT
LIMIT (Giới hạn) là một từ khóa không chuẩn, chỉ duy nhất của MySQL quy định cụ thể số lượng tối đa các hàng được trả về từ một truy vấn. DB2 sử dụng cú pháp FETCH FIRST n ROWS ONLY cho cùng một mục đích. Liệt kê 5 cho bạn thấy cách viết lại truy vấn với DB2.
Liệt kê 5. Quy định số lượng tối đa các hàng được trả về từ một truy vấn trong MySQL và DB2
-- In MySQL: 
SELECT * FROM ROLE LIMIT 10;

-- In DB2: 
SELECT * FROM ROLE FETCH FIRST 10 ROWS ONLY;
Mệnh đề GROUP BY
MySQL cho phép sử dụng một mệnh đề GROUP BY không chỉ rõ từng tên cột không được sử dụng bởi một hàm tổng hợp trong danh sách cột. Nhưng trong DB2, điều này là không hợp lệ, vì tập kết quả có thể có mức mơ hồ không thể chấp nhận được đối với nhiều người sử dụng. Liệt kê 6 cho thấy cách quy định rõ các cột trong truy vấn với DB2.
Liệt kê 6. So sánh các phép gộp GROUP BY hợp pháp trong MySQL và DB2
-- In MySQL: 
SELECT R.ID, R.NAME, COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.ID;
				
-- In DB2: 
SELECT R.ID, MIN(R.NAME), COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.ID;

-- Or
SELECT R.ID, R.NAME, COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.ID, R.NAME;

Trong Liệt kê 6, bạn có thể cập nhật GROUP BY, vì cả hai R.ID và R.NAME là khóa duy nhất trong bảng này. Liệt kê 7 cho thấy một loại truy vấn GROUP BY khác không thể xử lý đơn giản như truy vấn trong Liệt kê 6.

Liệt kê 7. GROUP BY không rõ ràng trong MySQL cần được sửa đổi cho DB2
-- In MySQL: 
SELECT R.ID, R.NAME, COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.NAME;

Trong trường hợp này, R.ID là duy nhất trong bảng, nhưng R.NAME thì không. Nếu có bản sao giá trị R.NAME trong bảng ROLE, thì bạn không thể thay thế R.ID bằng MIN(R.ID) và bạn không thể thêm R.ID vào mệnh đề GROUP BY. Cách bạn chuyển đổi SQL này như thế nào phụ thuộc vào bạn mong đợi kết quả dạng nào. Liệt kê 8 cho thấy một vài tùy chọn cho tình huống này.

Liệt kê 8. Truy vấn GROUP BY đã dịch trong DB2
-- In DB2: 
-- Option 1, if you want to get same result as what you get in MySQL, the SQL is: 
SELECT (SELECT RL.ID FROM ROLE RL WHERE RL.NAME = R.NAME FETCH FIRST 1 ROW ONLY) AS ID,
R.NAME, COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.NAME;
				
-- Option 2, if role name is same, treat it as same role. In this case, 
-- the result is a little different from MySQL version in that there is no R.ID:
SELECT R.NAME, COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.NAME;
				
-- Option 3, if role ID is different, treat them as different role. 
-- In this case, the result is totally different than the MySQL version:
SELECT R.ID, R.NAME, COUNT(U.ID) AS NUM 
FROM USER U, ROLE R 
WHERE U.ROLE_ID = R.ID 
GROUP BY R.ID, R.NAME;
REPLACE INTO trong MySQL so với MERGE trong DB2
MySQL cung cấp một mệnh đề REPLACE INTO. DB2 cung cấp một mệnh đề MERGE cho một mục đích tương tự, nhưng không tương đương. Để đạt được kết quả tương đương, hãy tạo ra một bản ghi mới hoặc thay thế một bản ghi hiện có nếu nó có khóa chính giống nhau hoặc giá trị duy nhất. Liệt kê 9 cho thấy cách kiểm tra một giá trị duy nhất trong bảng và hoặc cập nhật hoặc chèn các giá trị.
Liệt kê 9. Dịch cú pháp REPLACE INTO của MySQL sang DB2
-- In MySQL: 
REPLACE INTO ROLE (ID, NAME, DESCRIPTION)
SELECT ID, NAME, DESCRIPTION 
FROM ROLE_TMP;

-- In DB2: 
MERGE INTO ROLE R
USING (SELECT ID, NAME, DESCRIPTION FROM ROLE_TMP) RT
ON (R.ID = RT.ID)
WHEN MATCHED THEN
UPDATE SET (ID, NAME, DESCRIPTION) = (RT.ID, RT.NAME, RT.DESCRIPTION)
WHEN NOT MATCHED THEN
INSERT (ID, NAME, DESCRIPTION) VALUES (RT.ID, RT.NAME, RT.DESCRIPTION);
Mệnh đề JOIN
Khi thực hiện một phép nối (join) ngoài với một cặp bảng đồng thời cũng lấy ra dữ liệu từ một bảng thứ ba, hãy chỉ rõ các bảng được sử dụng cho phép nối ngoài kề ngay bên cạnh các từ khóa JOIN trong DB2. MySQL cho phép chúng được liệt kê theo bất kỳ thứ tự nào. Liệt kê 10 cho thấy sự thay đổi cần thiết.
Liệt kê 10. So sánh cú pháp JOIN của MySQL và DB2
-- Both of the following work in MySQL: 
SELECT * 
FROM USER U, ROLE R 
LEFT JOIN DEPARTMENT D 
ON U.DEPT_ID = D.ID;

-- Or
SELECT * 
FROM ROLE R, USER U 
LEFT JOIN DEPARTMENT D 
ON U.DEPT_ID = D.ID;

-- Only this one works in DB2: 
SELECT * FROM ROLE R, USER U 
LEFT JOIN DEPARTMENT D 
ON U.DEPT_ID = D.ID;
Các ký tự thoát
Ký tự \ biểu diễn một dấu gạch chéo ngược là mã thoát áp dụng cho dấu nháy đơn ' trong MySQL, nhưng trong DB2, một dấu nháy đơn phải được áp mã thoát bằng cách thêm một dấu nháy đơn khác " (hai dấu nháy đơn). Liệt kê 11 cho thấy một ví dụ về các dãy mã thoát cho một chuỗi ký tự sử dụng một dấu nháy đơn như là một dấu móc lửng.
Liệt kê 11. MySQL sử dụng dấu gạch chéo ngược để áp mã thoát cho các dấu nháy đơn, trong khi ở đó DB2 sử dụng một dấu nháy đơn thứ hai
-- In MySQL: 
SELECT * FROM ROLE 
WHERE DESCRIPTION = 'It\'s a super admin role';

-- In DB2: 
SELECT * FROM ROLE 
WHERE DESCRIPTION = 'It''s a super admin role';
Kiểm tra ngoài phạm vi trong DB2
MySQL không bắt buộc đúng phạm vi cho một kiểu dữ liệu trong một mệnh đề SELECT, nhưng DB2 thì có. Do đó SQL được hiển thị trong Liệt kê 12 để truy vấn thông tin trong khoảng thời gian từ 01.02 và 30.02 không làm việc trong DB2, nhưng nó làm việc trong MySQL.
Liệt kê 12. MySQL không kiểm tra dải các giá trị cho các mệnh đề WHERE dựa vào kiểu dữ liệu
-- MySQL allows you to specify February 30th as part of the range 
SELECT * FROM USER 
WHERE BIRTHDAY BETWEEN '1980-02-01' AND '1980-02-30';
CHÈN vào một cột NOT NULL không cần một giá trị mặc định
Trong MySQL, nếu bạn cố gắng thực hiện một câu lệnh INSERT mà không cung cấp một giá trị cho một cột NOT NULL, thì lệnh này vẫn thành công. MySQL tự động điền vào một giá trị mặc định, ngay cả khi bạn chưa bao giờ định nghĩa một giá trị mặc định cho cột đó khi tạo bảng. Tuy nhiên, trong DB2, bạn phải cung cấp một giá trị cho các cột NOT NULL trong một câu lệnh INSERT khi vẫn chưa đinh nghĩa một giá trị mặc định. Các câu lệnh SQL trong Liệt kê 13 cho thấy các hành vi xử lý khác nhau.
Liệt kê 13. MySQL và DB2 xử lý chèn các giá trị NULL một cách khác nhau
-- Works in both MySQL and DB2 
CREATE TABLE TEST1 (ID INTEGER, NAME VARCHAR(20) NOT NULL); 

-- Works in MySQL, doesn't work in DB2
INSERT INTO TEST1 (ID) VALUES(1); 

-- Works in both MySQL and DB2 				
CREATE TABLE TEST2 (ID INTEGER, NAME VARCHAR(20) NOT NULL DEFAULT ''); 

-- Works in both MySQL and DB2
INSERT INTO TEST2 (ID) VALUES(1);

Sử dụng các chế độ tương thích mới của DB2

Trong khi bạn có thể mô phỏng một số cú pháp MySQL bằng cách sử dụng các hàm do người dùng định nghĩa, có một lựa chọn khác là thiết lập một trong các chế độ tương thích dành cho các phiên bản của DB2 sau phiên bản 9.7.2. Đọc thêm về kích hoạt cú pháp LIMIT và OFFSET trên blog của Antonio Cangiano.

Chuyển đổi các hàm của MySQL thành các hàm tương tự của DB2
Bên cạnh SQL đặc thù riêng của MySQL, bạn cũng có thể đang sử dụng các hàm MySQL dựng sẵn. Bạn có thể thay thế các hàm này bằng các hàm SQL tiêu chuẩn hoặc các hàm tương đương có sẵn trong DB2. Tham khảo Phụ lục A: Ánh xạ các hàm dựng sẵn và các toán tử của MySQL trong Sách Đỏ Hướng dẫn chuyển đổi MySQL sang DB2 (xem phần Tài nguyên).

Như vừa được mô tả, nếu bạn không thể tìm thấy một hàm tương đương của DB2, thì bạn có thể viết lại SQL của mình để truy cập dữ liệu theo một cách khác. Ngoài ra, bạn có thể chọn mô phỏng hàm đó trong DB2 hoặc di chuyển logic vào mã PHP của mình, như được mô tả trong các phần sau.

Tạo các hàm do người dùng định nghĩa để mô phỏng các tính năng của MySQL

Nếu bạn không thể chỉ cập nhật các câu lệnh SQL theo cú pháp DB2 để đạt được cùng kết quả như các truy vấn MySQL của bạn, thì bạn có thể khắc phục bằng một cách khác dưới dạng một hàm do người dùng định nghĩa (UDF) trong SQL của DB2 để mô phỏng một hàm MySQL dựng sẵn.

Đã có một số chỗ sử dụng MySQL và PHP trong kịch bản ví dụ cần được tiếp cận theo cách khác khi cập nhật ứng dụng để sử dụng DB2. Cụ thể, bạn có thể di chuyển một số chức năng ra khỏi MySQL đưa vào PHP, ví dụ như khi thực hiện chuyển dịch ngày. Hoặc bạn có thể mô phỏng hàm trong DB2, ví dụ như để tạo các hàm do người dùng định nghĩa trong DB2 cho gần giống một số hàm được xây dựng trong MySQL, bao gồm cả UNIX_TIMESTAMP() và NOW(). Phụ lục B trong Sách Đỏ Hướng dẫn chuyển đổi MySQL sang DB2 (xem phần Tài nguyên) giải thích các sự khác biệt và đưa ra một cách tiếp cận để giải quyết các thay đổi. Những mẹo nhỏ của Daniel Krook đã thu thập được từ kinh nghiệm di trú của khách hàng của ông cũng rất có ích (xem phần Tài nguyên).

DML của DB2 khác với MySQL. Bài này mô tả cách chuyển đổi các SQL nhúng từ MySQL sang DB2. Tuy nhiên, không cần thiết chuyển đổi tất cả cú pháp từ MySQL sang DB2, đặc biệt là đối với các hàm dựng sẵn của MySQL. Phụ lục A. Ánh xạ các hàm dựng sẵn và các toán tử của MySQL trong Sách Đỏ Hướng dẫn chuyển đổi MySQL sang DB2 (xem phần Tài nguyên) liệt kê rất nhiều hàm dựng sẵn của MySQL. Nói chung, nhiều hàm có thể được chuyển đổi thành các UDF của DB2. Bạn quyết định sẽ chuyển đổi các hàm dựng sẵn nào thường được sử dụng. Đối với kịch bản ví dụ, cũng đáng bỏ công sức sử dụng các UDF của DB2 để chuyển đổi các hàm hoặc các thanh ghi của MySQL nếu bạn sử dụng chúng thường xuyên. Sau đây là một danh sách các hàm và các thanh ghi của MySQL mà bạn có thể chuyển đổi.

  • CURRENT_DATE() / CURDATE()
  • DATE_FORMAT()
  • DATEDIFF()
  • FROM_UNIXTIME()
  • NOW()
  • PERIOD_DIFF()
  • TO_DAYS()
  • UNIX_TIMESTAMP()
  • WEEKDAY()
  • YEARWEEK()

Thật may, rất nhiều hàm nói trên đã được triển khai thực hiện và có sẵn miễn phí để sử dụng lại, như đã trình bày trong bài "Cơ sở về DB2: Trò vui với các ngày và giờ " (xem phần Tài nguyên). Nếu bạn đang sử dụng phiên bản v9.7.2 hoặc mới hơn của DB2, bạn có thể chọn thiết lập vector tương thích mới DB2_COMPATIBILITY_VECTOR=MYS.

DB2 tạo dễ dàng các hàm do người dùng định nghĩa, do chúng có thể được viết bằng SQL thay vì yêu cầu sử dụng ngôn ngữ lập trình C, như trong trường hợp MySQL.

Liệt kê 14 là một ví dụ về một UDF mà bạn có thể tạo ra để mô phỏng hàm NOW() của MySQL không chuẩn nhưng thường được sử dụng. Bạn có thể sử dụng mô phỏng này ở nhiều nơi trong ứng dụng ví dụ.

Liệt kê 14. Định nghĩa một UDF của DB2 để mô phỏng hàm dựng sẵn NOW() của MySQL
CREATE FUNCTION NOW()
	RETURNS TIMESTAMP
	NO EXTERNAL ACTION

	BEGIN ATOMIC
		RETURN SELECT CURRENT TIMESTAMP
		FROM SYSIBM.DUAL;
	END

Có một số hàm khác do người dùng định nghĩa để mô phỏng các hàm dựng sẵn hay dùng của MySQL được liệt kê trong Phụ lục B của Sách Đỏ Hướng dẫn chuyển đổi MySQL sang DB2 (xem phần Tài nguyên).

Di chuyển logic từ SQL sang PHP nếu cần

Có thể có các tình huống ở đó bạn không thể chuyển các hàm hoặc cú pháp của MySQL sang một định dạng thuận tiện của DB2. Trong trường hợp này, hãy xem xét liệu chính PHP có hỗ trợ tính năng ấy không và sử dụng hàm hoặc phần mở rộng đó để thay thế. Ví dụ, MySQL cung cấp một hàm SQL gọi là INET_ATON(), không có hàm tương đương trong DB2. Viết một hàm do người sử dụng định nghĩa thay cho INET_ATON() có thể tẻ nhạt và dễ mắc lỗi. May thay, PHP cung cấp hàm ip2long () có cùng chức năng và không phụ thuộc vào nhà cung cấp cơ sở dữ liệu.


Bước 2: Bắt đầu bước chuyển thứ hai trong di trú mã

Với mã PHP được cập nhật để sửa đổi các câu lệnh SQL nhúng và để đọc hoặc cập nhật dữ liệu một cách tương tự như MySQL, bước tiếp theo là cấu trúc lại các truy vấn của bạn để đạt được các mục tiêu không có tính chức năng về toàn vẹn dữ liệu và cải thiện hiệu năng tốt hơn. Bước này liên quan đến các bước nhỏ sau đây:

Chọn cách tiếp cận thích hợp để xử lý đồng thời

Khi các truy vấn riêng lẻ được nhúng trong ứng dụng dựa vào MySQL đã được chuyển đổi để làm việc trên DB2 theo một mẫu tương đương, thì đây là lúc để xem xét cách có thể cải thiện chúng như thế nào để lợi dụng các tính năng xử lý đồng thời và toàn vẹn dữ liệu của DB2. Hãy xem xét các thay đổi cần thiết để hỗ trợ các mức cách ly thích hợp giữa một số kết nối đồng thời tới cơ sở dữ liệu.

Có bốn mức cách ly trong DB2 để kiểm soát xử lý đồng thời. Các mức cách ly xác định cách một giao dịch ẩn giấu các thay đổi dữ liệu đang thực hiện khỏi những người dùng khác. Các mức cách ly như sau:

Mức cách ly đọc lặp lại (RR)
Tất cả các hàng bị khóa cho đến khi kết thúc giao dịch.
Mức cách ly ổn định đọc (RS)
Các hàng thỏa mãn điều kiện biến vị ngữ bị khóa cho đến khi kết thúc giao dịch.
Mức cách ly ổn định con trỏ (CS)
Chỉ có những hàng nào con trỏ đang trỏ vào bị khóa. Đây là mặc định.
Mức cách ly đọc không cam kết (UR)
Không có hàng nào bị khóa trừ khi dữ liệu đang thay đổi.

Hãy xem xét mức cách ly nào phù hợp với ứng dụng của bạn từ một góc độ hiệu năng và tính toàn vẹn dữ liệu. Việc xử lý đồng thời giảm đi và tính toàn vẹn dữ liệu tăng lên khi bạn di chuyển mức cách ly từ đọc không cam kết (UR) sang đọc lặp lại (RR). Mức cách ly RR đảm bảo tính toàn vẹn dữ liệu tối đa phải trả bằng giá hiệu năng cao. Ngược lại, UR đảm bảo mức hiệu năng cao nhất phải trả bằng giá không nhất quán dữ liệu nào đó. Hình 1 minh họa các mối quan hệ giữa hiệu năng và tính toàn vẹn dữ liệu.

Hình 1. Các mức cách ly trong DB2
Sơ đồ với các khối RR, RS, CS và UR giảm dần theo chiều dọc. Thang đo toàn vện dữ liệu cao nhất ở RR. THang đo hiệu năng cao nhất ở UR

Bạn có thể quy định mức cách ly ở các mức khác nhau, từ các truy vấn riêng lẻ lên đến toàn bộ các kết nối và phiên làm việc đó. Nếu bạn có một tải công việc đọc rất nhiều, bạn có thể muốn thiết lập mức cách ly là đọc không cam kết (UR) ở mức kết nối để cho bạn không phải chỉ rõ nó trong mỗi câu lệnh. Nếu bạn có sự kết hợp các công việc đọc và viết, bạn có thể muốn tập trung vào chỉnh sửa các truy vấn riêng lẻ hơn là chỉ thay đổi khỏi mức cách ly mặc định là ổn định con trỏ (CS).

Bạn có thể cũng muốn xem xét kiểu con trỏ mà bạn nên sử dụng để tối ưu hóa truy cập dữ liệu. Cả hai trình điều khiển ibm_db2 lẫn PDO_IBM đều hỗ trợ hai kiểu con trỏ: con trỏ chỉ tiến lên và con trỏ có thể cuộn được. Con trỏ mặc định là con trỏ chỉ tiến lên. Nói chung, con trỏ mặc định là một sự lựa chọn tốt cho phần lớn các trường hợp sử dụng, ở đó bạn lần lượt duyệt qua một tập kết quả. Xét về hiệu năng, con trỏ chỉ tiến lên tốt hơn so với con trỏ có thể cuộn được. Tuy nhiên, trong một số trường hợp, bạn sẽ cần phải đọc các con trỏ cả tiến lên và lùi lại, trong trường hợp này bạn nên sử dụng con trỏ cuộn. Trong kịch bản ví dụ, kiểu con trỏ được thiết lập bằng các lệnh trong Liệt kê 15 cho mỗi truy vấn cần thiết.

Liệt kê 15. Định nghĩa kiểu cuộn của DB2 từ các hàm ibm_db2 và trình điều khiển PDO
-- For ibm_db2
db2_exec($connection_resource, $sql, array('cursor' => DB2_SCROLLABLE));

-- For PDO_IBM
$DB_PDO->prepare($sql, array(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL));

Xem mục 4.2 Sử dụng PHP với cơ sở dữ liệu DB2 trong Sách Đỏ Phát triển các ứng dụng PHP cho các máy chủ dữ liệu của IBM (xem phần Tài nguyên) để biết thêm chi tiết.

Hợp nhất các truy vấn để cải thiện chất lượng và hiệu năng dữ liệu

Tiếp theo, hãy nhóm các truy vấn thành các đơn vị lô-gic chứ không phải là các truy vấn độc lập. Trong bước chuyển di trú mã này, một khi bạn biết rằng các câu lệnh SQL đều đang nhận cùng một dữ liệu kết quả và các câu lệnh đều đang sửa đổi dữ liệu như chúng đã làm trong ứng dụng cũ, hãy xem xét việc nhóm lại các truy vấn truy cập và các cập nhật dữ liệu. Mục đích là để làm cho có mức hiệu năng của MySQL trong khi vẫn đảm bảo mức độ toàn vẹn dữ liệu của DB2.

Thu hẹp tỷ lệ các kết nối cơ sở dữ liệu so với các câu lệnh
Nói chung, xây dựng một kết nối đến cơ sở dữ liệu trong MySQL thì nhanh hơn trong DB2. Do đó việc giảm số lượng tổng cộng các kết nối cho mỗi yêu cầu HTTP bằng cách sử dụng lại một kết nối cho nhiều hơn một truy vấn sẽ cải thiện hiệu năng của bộ xử lý, ổ đĩa và mạng. Với kịch bản ví dụ, các truy vấn được hợp nhất, bao gồm việc lấy thông tin tài khoản người dùng để thực hiện sẵn trước các phép nối nối rộng hơn (chứ không sử dụng một số các truy vấn tìm kiếm tiếp theo), như trong Liệt kê 16. Việc này có thể dẫn đến phải trả giá bằng việc tìm nạp trước quá nhiều dữ liệu, nhưng với kịch bản ví dụ này, hiệu năng được cải thiện, số lượng dữ liệu đã tìm nạp đã được giảm bớt và các nhà phát triển đã có một ý tưởng tốt hơn về thực sự cần lấy ra bao nhiêu dữ liệu cho một trang nhất định, do đó cũng tiết kiệm tài nguyên.
Liệt kê 16. Hợp nhất các truy vấn
-- Two individual queries that require two trips to the data server on the page
SELECT FIN_PROJECT_MANAGER AS PM, PROJNAME FROM PROJECT WHERE ID = $id;
SELECT EMAIL, FIRSTNAME, LASTNAME FROM USER WHERE ID = $pm;

-- Single consolidated query that retrieves the same information in one trip
SELECT U.EMAIL, U.FIRSTNAME, U.LASTNAME
FROM USER U, PROJECT P
WHERE U.ID = P.FIN_PROJECT_MANAGER 
AND PROJECT.ID = $id

Tại sao không di trú Zend Framework?

Cơ sở mã cho kịch bản ví dụ đã có trước hầu hết các khung công tác cho PHP. Các thành phần có thể sử dụng lại được từ PEAR và các thư viện mục đích đặc biệt như các tầng trừu tượng cơ sở dữ liệu đang bắt đầu có được sức lôi cuốn khi chúng tôi bắt đầu viết PTT vào năm 2002. Các khung công tác đủ trọn vẹn cả chồng công nghệ như CakePHP và Zend Framework chỉ xuất hiện nhiều năm về sau. Việc chấp nhận Zend Framework là một mục tiêu mong muốn trong tương lai, nhưng việc cập nhật mã ổn định để thay thế cơ sở dữ liệu và bắt đầu đặt các nền móng cho điều đó đã là phạm vi bao quát chính của việc di trú mã này.

Cải tiến hướng đến một kiến trúc MVC dễ duy trì hơn
Trong một ứng dụng web ba tầng có thiết kế tốt được xây dựng bằng cách sử dụng mẫu kiến trúc của mô hình-khung nhìn-trình điều khiển (MVC), trình điều khiển xử lý một yêu cầu web từ một người dùng và sau đó gọi một lệnh trên mô hình để chuẩn bị một kết quả. Đối tượng kết quả này được chuyển giao cho khung nhìn (thường biểu diễn bằng một khuôn mẫu HTML đơn giản) để hiển thị dữ liệu đáp ứng trên trang. Ứng dụng ban đầu đã không sử dụng mẫu MVC. Thay vào đó, ứng dụng đã nhúng các truy vấn trực tiếp vào các khuôn mẫu, hòa trộn thực sự cả ba nhiệm vụ vào một trang.

Bằng việc chấp nhận một hướng dẫn thực hành tốt nhất về tạo nhóm các truy vấn của MVC, như lấy tất cả các thông tin tài khoản người dùng và tất cả các dự án cho người dùng đó trong một cuộc gọi duy nhất đến mô hình, trang khung nhìn chỉ cần hiển thị thông tin, chứ không phải là từng bước tìm nạp thêm nhiều dữ liệu hơn. Cách tiếp cận này chuyển ứng dụng từ dữ liệu làm trung tâm hướng tới đối tượng nghiệp vụ làm trung tâm và do đó có thể giúp tổ chức mã của bạn tốt hơn bằng cách phân tách logic truy cập dữ liệu khỏi đánh dấu thiết kế và bố trí trang.

Phân phối tốt hơn tải tính toán
Bởi vì kịch bản ví dụ đã có một máy chủ web riêng và một máy chủ cơ sở dữ liệu riêng, nên máy chủ web chủ yếu là xử lý khối lưu lượng HTTP rất lớn. Máy chủ web đã thực hiện lô-gic phía máy chủ thông qua mô đun PHP. Để cải thiện hiệu năng ở máy chủ HTTP bằng cách giảm tiêu thụ CPU và bộ nhớ mà máy chủ web đã dùng trong mod_php, một số logic nghiệp vụ đã được chuyển cho máy chủ dữ liệu. Điều này đã thường mang lại thêm lợi ích, làm giảm tổng lưu lượng mạng (vì nó làm giảm lưu thông giữa máy chủ web và máy chủ dữ liệu) và do đó khả năng thông qua được tăng lên nhờ xử lý dữ liệu ở cùng một mức như nó đã được truy cập.
Cải thiện tính toàn vẹn dữ liệu bằng cách nhóm các truy vấn trên máy chủ
Lợi ích cuối cùng và quan trọng nhất cho sự toàn vẹn giao dịch là nhóm lô-gic xử lý thành các đơn vị giao dịch nguyên tử trên máy chủ dữ liệu khi sử dụng các thủ tục đã lưu, các tri-gơ và các hàm do người dùng định nghĩa. Bạn sẽ thấy rằng việc tạo các nhiệm vụ trong một ứng dụng như PTT đáng tin cậy hơn khi những điều sau đây xảy ra:
  • Tất cả các dữ liệu được chuyển giao toàn bộ tới cơ sở dữ liệu.
  • Nhiều câu lệnh INSERT được thực hiện cùng nhau như là một đơn vị.
  • Chỉ trả về cho người dùng một kết quả thành công hay một lỗi đã thất bại.
Nếu không có một cơ sở dữ liệu đã hỗ trợ các giao dịch, thì một hoặc tất cả các sửa đổi cơ sở dữ liệu này có thể đã thất bại trong kịch bản ví dụ, do đó để lại hệ thống trong một trạng thái không thể dự đoán được, đòi hỏi có sự can thiệp của người dùng hoặc của nhà quản trị để giải quyết sự không nhất quán của dữ liệu, ví dụ như một nhiệm vụ chỉ được tạo một phần mà không có một chủ sở hữu hoặc liên kết quan trọng khác. Liệt kê 17 cho thấy một ví dụ về hai bản cập nhật có liên quan với nhau xảy ra như là một đơn vị nguyên tử.
Liệt kê 17. Nhóm các bản nhật thành một thủ tục lưu sẵn
CREATE PROCEDURE BILLING_TYPE_UPDATE (IN p_date DATE)
BEGIN
    -- Update for project's billing type
    FOR row AS 
       SELECT * 
       FROM proj_billingtype_snapshot
       WHERE end_date IS NULL
       AND start_date = p_date
       
	    DO
	       -- Execute two updates in one transaction
	       t1: begin atomic   -- Transaction begins
	      
	       -- First update
	       UPDATE fin_attributes
	       SET proj_type = row.billing_type
	       WHERE project_id = row.proj_id;
	        
	       -- Second update
	       UPDATE fin_attributes_archive
	       SET proj_type = row.billing_type
	       WHERE project_id = row.proj_id
	       AND year = YEAR(NOW());
	          
	       end t1;            -- Transaction ends
    END FOR;
END

Tất cả các phiên bản của DB2 đều hỗ trợ các giao dịch, nhưng hầu hết các máy lưu trữ MySQL, bao gồm cả kiểu mặc định MyISAM, lại không hỗ trợ chúng. Ứng dụng ví dụ được xây dựng bằng cách sử dụng kiểu bảng MyISAM mặc định và các nhà phát triển đã cố gắng thực thi tính toàn vẹn dữ liệu ở mức mã. Cho nên việc di chuyển sang DB2 được chào đón vì đã có thể ủy thác quản lý giao dịch cho cơ sở dữ liệu, một việc mà DB2 làm rất tốt. Nó cũng làm giảm kích thước tổng thể và độ phức tạp của mã và các phần di chuyển khác nhau cần thiết để làm việc cùng nhau trên bất kỳ trang PHP cụ thể nào trong ứng dụng. Xem phần 5.2.8 Các giao dịch và mức cách ly trong Sách Đỏ Các ứng dụng của PHP cho các máy chủ dữ liệu của IBM (xem phần Tài nguyên) để tìm hiểu thêm về xử lý đồng thời trong DB2.


Bước 3: Bắt đầu kiểm tra trường hợp sử dụng nghiệp vụ lần đầu với các bên liên quan

Vào lúc này, bạn phải có một hệ thống đang hoạt động có thể được kiểm tra toàn bộ hoặc ít nhất là một tập các chức năng có liên quan có một thành phần cụ thể. Ví dụ, việc tạo một nhiệm vụ mới được gắn với một dự án mẹ là một trường hợp sử dụng khá độc lập trong hệ thống PTT. Việc gửi một phần nội dung, ví dụ như một tiêu đề và mô tả sản phẩm, đến một dịch vụ dịch thuật là một trường hợp sử dụng khác có thể được kiểm tra độc lập. Bước chuyển đổi này bao gồm các bước nhỏ sau:

Biên dịch hoặc tạo các bài kiểm thử chấp nhận bởi người dùng

Trong bước này, hãy bắt đầu đưa các bên liên quan quan tâm vào cuộc để thực thi một loạt các trường hợp sử dụng thường được thực hiện trong hệ thống cũ. Bạn muốn đảm bảo rằng cùng loạt các bài kiểm thử này làm việc như mong đợi trên hệ thống mới.

Kịch bản ví dụ đã sử dụng một định dạng khá chuẩn cho việc kiểm tra chấp nhận của người dùng trong những năm qua. Vì vậy, có một kho lưu trữ các bài kiểm thử để xác nhận hợp lệ các tính năng mới và để tránh các vấn đề hồi quy với mã hiện có. Danh mục kiểm tra được mở rộng để chứa các hàm trọng yếu đối với chức năng của PTT. Các bài kiểm thử này thường chứa một tập các bước có liên quan để đạt được một mục tiêu nghiệp vụ và chúng trông giống như một sơ đồ trường hợp sử dụng. Sự khác biệt so với một mô hình trường hợp sử dụng tĩnh là các bài kiểm thử thường được lưu trữ theo một định dạng bảng tính cùng với các ảnh chụp màn hình và các bảng có các hàng có thể cập nhật được, ở đó một người kiểm thử có thể nhập một loạt các bước cụ thể hay các bước riêng lẻ cho dù có thành công hoặc thất bại. Bảng 1 cho thấy một ví dụ về định dạng của trường hợp kiểm thử chấp nhận bởi người dùng để xác minh xem việc tạo nhiệm vụ đó đã làm việc như đã mong đợi chưa.

Bảng 1. Bài kiểm thử chấp nhận bởi người dùng mẫu
TestExpected resultPassed?
1. Tạo một nhiệm vụ mới1.1 Đăng nhập vào hệ thống.Trang chào đón được hiển thị.
1.2 Mở trang nhiệm vụ mới.Tải biểu mẫu nhiệm vụ mới.
1.3 Điền vào biểu mẫu và lưu trữ.Hiển thị thông báo thành công và liên kết của ID duy nhất của nhiệm vụ.
2. Phê duyệt nhiệm vụ2.1 Log into the system.Trang chào đón được hiển thị.
2.2 Đăng nhập vào hệ thống.Danh sách các tải công việc.
2.3 Định vị danh sách các nhiệm vụ.Hiển thị thông báo thành công và gửi email. Không

Hãy ghi nhớ rằng điều cực kỳ quan trọng là những người kiểm thử của bạn dành đủ thời gian để thực hiện các bài kiểm thử chấp nhận bởi người dùng và ghi lại bất kỳ vấn đề nào. Nếu họ chỉ đọc lướt các bài kiểm thử, họ có thể bỏ sót các lỗi. Cũng với lý do tương tự, điều quan trọng là lập sổ ghi ai đã kiểm thử vào lúc nào và các kết quả họ đã báo cáo là gì để thực thi trách nhiệm giải trình.

Bài kiểm thử đơn vị và sửa lỗi

Bước này đòi hỏi phân tích có hệ thống các vấn đề do những người kiểm thử chấp nhận bởi người dùng báo cáo. Khi nhận được các bài kiểm thử chấp nhận bởi người dùng từ những người kiểm thử, cần giao cho cá nhân các nhà phát triển những vấn đề đã được báo cáo để xác nhận và sửa chữa. Ví dụ, bài kiểm thử 2.3 trong Bảng 1 sẽ được quy như là một lỗi mới.

Khi bạn di trú hệ thống theo cách lặp nhiều lần, các nhà phát triển cần so sánh chức năng đã di trú vào DB2 với hệ thống nguồn MySQL ban đầu để đảm bảo rằng các đơn vị công việc cụ thể được thực hiện như mong đợi. Với các bài kiểm thử chấp nhận bởi người dùng, sẽ rất có giá trị nếu tự động hóa quá trình này bằng cách sử dụng một khung công tác kiểm thử đơn vị, ví dụ như PHPUnit. Vì cơ sở mã ví dụ không được phân chia đúng thành mã MVC, thích hợp với dễ kiểm thử theo chương trình, nên bài kiểm thử đơn vị tự động hóa hoặc hệ thống tích hợp liên tục không được sử dụng.

Chụp một ảnh để dùng làm vạch chuẩn

Sau khi phần chính của các trường hợp sử dụng đã hoàn thành, bước cuối cùng trước khi bắt đầu một vòng lặp kiểm thử mới là chụp ảnh hiện trạng hệ thống làm một bản sao lưu và một vạch chuẩn để tham chiếu lại khi kiểm tra xác nhận hoạt động và hiệu năng. Một lần nữa, mỗi khi các vòng lặp thay đổi đạt đến một mốc ổn định, điều quan trọng là chụp ảnh các bản sao lưu. Ảnh này có thể là dạng tệp truyền thống và các bản sao lưu SQL hoặc có thể là dạng các ảnh hoàn chỉnh của hệ điều hành. Điều rất quan trọng nữa là duy trì các điểm lưu trữ này trong trường hợp có một lỗi trong tương lai hoặc để sử dụng làm một vạch chuẩn so sánh.


Bước 4: Giải quyết nút nghẽn cổ chai và xác nhận dựa vào vạch chuẩn chức năng

Một khi tập hoàn chỉnh các bài kiểm thử chấp nhận bởi người dùng đã được các bên liên quan của bạn ký duyệt, đây là lúc để cải thiện hiệu năng của hệ thống. Bước này đòi hỏi hoàn thành các bước sau đây:

Xác nhận các bài kiểm thử UAT vạch chuẩn

Với bước chuẩn bị này, điều quan trọng cần nhắc lại là bạn cần có một khung nhìn rõ ràng về chức năng hệ thống đã xác nhận sao cho bạn biết liệu có bất kỳ yêu cầu cải tiến phi chức năng nào không, ví dụ như các cải tiến hiệu năng, có ảnh hưởng tốt hoặc phải đánh đổi bằng các yêu cầu chức năng đã thống nhất. Bước này nên diễn ra sau khi kiểm tra xác nhận chức năng vì hai lý do. Đầu tiên, nó đảm bảo rằng bạn có một vạch chuẩn chức năng đã được ký duyệt, đã được biết rõ trước khi thực hiện bất kỳ các thay đổi phi chức năng nào. Thứ hai, nó giúp bạn tránh các cạm bẫy của việc tối ưu hóa vội vàng trong việc di trú của bạn. Bạn có thể biết rằng một truy vấn hoặc cách tiếp cận nào đó nhanh hơn trong một trường hợp, nhưng bạn không nên áp dụng một cách mù quáng một sự thay đổi trên toàn bộ cơ sở mã, đặc biệt là khi không có dấu hiệu nào cho thấy có một vấn đề hiệu năng.

Lấy ví dụ, một lịch sử các bài kiểm thử chấp nhận bởi người dùng đã được lưu giữ để xác nhận liệu có gì đó đã được kiểm thử và thành công trước đó chưa để dùng kiểm tra các vấn đề hồi quy nếu chúng xuất hiện sau này.

Sử dụng các công cụ để sửa chữa các vấn đề hiệu năng trong DB2

Những mối hiểm họa của việc tối ưu hóa vội vàng

Có khả năng bạn đã nghe nói về nhận xét của Donald Knuth vào năm 1974 rằng "việc tối ưu hóa vội vàng là gốc rễ của mọi tội lỗi". Một ví dụ về các cạm bẫy của vấn đề này xuất phát từ kinh nghiệm của một trong những tác giả của loạt bài này (chúng tôi không nêu rõ tên người phạm lỗi!). Khi ông đã biết rằng các chuỗi ký tự dùng dấu nháy đơn thực hiện tốt hơn so với các chuỗi ký tự dùng dấu nháy kép (do thực tế là các biến nội suy không bị thay thế khi được bọc trong các dấu nháy đơn), ông đã quyết định có lẽ thật tốt để thay thế tất cả các dấu nháy kép bằng các dấu nháy đơn. Ông đã không có lý do nào để nghĩ rằng ứng dụng này đã đang có các vấn đề hiệu năng, nên ông đã thực hiện những gì ông nghĩ là tìm kiếm và thay thế cẩn thận hơn. Thật không may, ông đã bỏ sót một hoặc hai chuỗi nội suy và đưa vào một lỗi rất khó phát hiện, đã gây ra các vấn đề toàn vẹn dữ liệu trong tương lai. Tuy nhiên, chúng tôi đã tha lỗi cho ông.

Việc kiểm thử của bạn vào thời điểm này nên tập trung chủ yếu vào những gì DB2 có thể sửa chữa tự động cho bạn, vì DB2 là sự thay đổi lớn nhất mà bạn đưa vào. Khi bạn thay đổi mã, bài kiểm thử đơn vị và thực hiện kiểm thử chấp nhận bởi người dùng (UAT), bạn nên xác định các nút nghẽn cổ chai và thực hiện các thay đổi khi cần. Một triết lý quan trọng cần làm theo là chỉ thay đổi những điều đã biết là có vấn đề thông qua bài kiểm thử đơn vị và việc kiểm tra UAT còn hơn là thực hiện các giả định về các nguồn tiềm năng của các vấn đề hiệu năng. Sau khi thực hiện điều này, bạn có thể cung cấp những gì đã được thay đổi và ghi lại nó để các ứng dụng tương lai chống lại các lỗi sau này.

Có một sự cân bằng mong manh giữa việc tối ưu hóa vội vàng và áp dụng các bản sửa lỗi trên diện rộng dựa vào một danh sách các hướng dẫn thực hành tốt nhất. Đây sẽ là một quá trình lặp lại trong suốt vòng đời của ứng dụng. Xem phần bên về các mối hiểm họa của việc tối ưu hóa vội vàng.

Một kỹ thuật mà bạn có thể thấy có ích là thực hiện một hàm, giám sát các kịch bản lệnh chạy quá 60 giây và gửi một báo cáo lỗi, như đã được thực hiện cho ứng dụng ví dụ PTT. Một ví dụ của hàm này được mô tả trong phần 4 của loạt bài này.

Dựa vào thông tin có sẵn trong báo cáo đó, bạn có thể phát hiện ra là liệu có vấn đề phát sinh ra từ một kết quả của việc thực hiện PHP chậm hay một truy vấn chậm không. Với các vấn đề về PHP, một trình gỡ lỗi như trình gỡ lỗi có sẵn trong Zend Studio hoặc Eclipse PDT có thể giúp bạn định vị các vấn đề. Với các vấn đề truy vấn, bạn có thể sử dụng IBM Data Studio để định vị các vấn đề và đề xuất sửa chữa. Hình 2 cho thấy một ví dụ của biểu đồ kế hoạch truy cập cho một truy vấn cụ thể.

Hình 2. Tinh chỉnh một truy vấn trong IBM Data Studio
Biểu đồ lưu lượng hiển thị các ngăn tiếp theo các tìm nạp (fetche) và các lần quét (scant), rồi lên đến nối (join) và quay về (return)

Định vị và giải quyết các nút nghẽn cổ chai trong hệ điều hành

Nếu bạn đã chắc DB2 và PHP không phải là nguồn gốc của các vấn đề hiệu năng của ứng dụng của bạn, thì bạn nên định vị lặp lại nhiều lần các nút nghẽn cổ chai khác bằng cách sử dụng các hướng dẫn thực hành tốt nhất về thử - và - đúng được mô tả trong "Các mẫu PHP mức doanh nghiệp của Zend" của John Coggeshall (xem phần Tài nguyên). Tóm lại, bạn có thể bắt đầu xem xét ba nguồn gốc phổ biến của các nút nghẽn cổ chai của ứng dụng để xem xem bạn có thể giải quyết bất kỳ các vấn đề hiệu năng nào không thông qua việc nâng cấp phần cứng đơn giản hoặc bằng cách điều chỉnh các tài nguyên được phân phối cho một máy ảo:

  • CPU
  • Bộ nhớ
  • Đĩa

Trong khi nhiều công cụ được sử dụng để xác định các nút nghẽn cổ chai trong cuốn sách của Zend áp dụng cho các hệ điều hành Linux, thì nhiều kỹ thuật có thể đạt được với các công cụ đặc trưng của Windows khi bạn đang phát triển hoặc sau khi bạn triển khai ứng dụng đã cập nhật của bạn tới một máy chủ thử nghiệm hay máy chủ tạm và tiếp tục lại sau khi triển khai.


Bước 5. Đánh giá vạch chuẩn về di trú mã

Sau một vòng lặp toàn bộ các bước 1 đến 4, mà mỗi bước trong đó lại gồm vài bước chuyển, bạn sẽ có một hệ thống cơ sở dữ liệu hoạt động được trên một máy trạm Windows và vài ghi nhớ về những gì bạn đã thay đổi và những gì đã có vấn đề. Nếu bạn đã sử dụng các máy ảo, bạn có thể chụp một hình ảnh của hệ thống Windows như một ảnh chụp màn hình, vừa để lưu trữ làm một điểm ghi lưu thực hiện chức năng và vừa để sử dụng làm một vạch cơ sở để so sánh với các thay đổi hiệu năng trong tương lai. Tất nhiên, có một tùy chọn khác là sử dụng một ảnh ảo trong Đám mây của IBM hay của Amazon và sử dụng đám mây theo cùng cách. Bạn có thể muốn thử nghiệm với vài bản cập nhật mã khác nhau để xem xét những gì làm việc tốt nhất cho môi trường của bạn.

Một khi bạn đã cảm thấy hài lòng với hệ thống trên máy trạm Windows được sử dụng trong các bước 1-4, bạn có thể gắn thẻ cho mã đã chuyển đổi của bạn như một phát hành trong hệ thống kiểm soát phiên bản của bạn và chuẩn bị cơ sở hạ tầng cho các bước cuối cùng trước khi triển khai như mô tả trong phần 4 của loạt bài này.


Kết luận

Mục đích của loạt bài này là cung cấp cho bạn một sự hiểu biết về những gì thường cần thiết để di trú một ứng dụng PHP từ MySQL sang DB2, các tài nguyên nào có sẵn để giúp bạn và một ví dụ về một cuộc di trú thành công.

Trong phần thứ ba này của loạt bài, bạn:

  • Đã học về mã nguồn PHP mà bạn đã chuyển đổi.
  • Đã học cách cập nhật ứng dụng cho DB2.
  • Đã học cách kiểm thử và điều chỉnh sau khi bạn đã chuyển đổi nó.

Trong phần 4, bạn sẽ tìm hiểu cách triển khai ứng dụng đã di trú và xử lý sự hỗ trợ đang có.


Lời cảm ơn

Các tác giả cảm ơn Leons Petrazickis và Ambrish Bhargava đã đọc lại và góp ý kiến cho bài này.

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Information Management, Nguồn mở
ArticleID=793458
ArticleTitle=Di chuyển một ứng dụng PHP từ MySQL sang DB2, Phần 3: Chuyển đổi mã PHP của bạn
publish-date=02142012