Tập lệnh sao lưu đó thật lố bịch và không ai nên tạo một phiên bản khác của nó. Tôi đã từng thấy tập lệnh đó trước đây, cũng như những lần thử tương tự và chúng gặp rất nhiều vấn đề:
- Không phân tách tên bảng bằng dấu tích lại
- Không xử lý NULL
- Không xử lý các bộ ký tự
- Không xử lý dữ liệu nhị phân
- Không sao lưu VIEWs
- Không sao lưu TRIGGER hoặc THỦ TỤC ĐƯỢC LƯU TRỮ hoặc CÁC CHỨC NĂNG hoặc SỰ KIỆN ĐƯỢC LƯU TRỮ
- Sử dụng tiện ích mở rộng mysql lỗi thời (nhưng đây là lý do tại sao bạn muốn có phiên bản PDO, phải không?)
- Sử dụng thêm dấu gạch ngang () thay vì một hàm thoát MySQL thích hợp.
- Áp dụng tất cả dữ liệu cho tất cả bảng thành một chuỗi thực sự dài, trước khi xuất toàn bộ nội dung. Điều này có nghĩa là bạn phải có khả năng lưu trữ toàn bộ cơ sở dữ liệu của mình trong một chuỗi, điều này gần như chắc chắn sẽ làm giảm giới hạn bộ nhớ tối đa PHP của bạn.
Xem thêm câu trả lời trước đây của tôi về tập lệnh sao lưu David Walsh không may:
Nhận xét lại của bạn:
Đọc các bình luận trên trang bạn đã liên kết đến. Rất nhiều người đã xác định được các vấn đề và một số có các bản sửa lỗi hoặc ít nhất là các đề xuất.
Tôi nghĩ rằng thực tế là tập lệnh này nối mọi thứ thành một chuỗi là một công cụ phá vỡ thỏa thuận, nhưng không khó để thay đổi tập lệnh để mở tệp đầu ra đầu tiên , sau đó xuất dữ liệu của từng hàng trong vòng lặp, rồi đóng tệp sau vòng lặp. Đó là điều không cần phải bàn cãi, tôi không chắc tại sao kịch bản lại không làm như vậy. Nhưng rõ ràng là tập lệnh không được kiểm tra tốt.
Nhưng dù sao đi nữa, tôi sẽ không cố gắng phát minh lại bánh xe này. Mysqldump hoặc mydumper làm tốt công việc này. FWIW, bạn không phải chạy mysqldump trên cùng một máy chủ nơi cơ sở dữ liệu nằm. Mysqldump hỗ trợ một tùy chọn cho --host
vì vậy bạn có thể chạy mysqldump ở bất kỳ đâu để sao lưu cơ sở dữ liệu từ xa, miễn là tường lửa không chặn máy khách của bạn kết nối. Về cơ bản, nếu bạn có thể kết nối một ứng dụng PHP với cơ sở dữ liệu từ một số máy khách, bạn có thể kết nối mysqldump.
Nếu đó thực sự không phải là một tùy chọn, thì tôi sẽ sử dụng tính năng kết xuất cơ sở dữ liệu của phpmyadmin. Chúng đã trưởng thành và được kiểm tra kỹ lưỡng và chúng đổ mọi thứ một cách chính xác. Đây là bài viết mô tả cách sử dụng tính năng kết xuất:
[Sao chép nhận xét của tôi từ câu trả lời của bạn:]
Đây là việc xem xét mã, không phải là mục đích của StackOverflow. Nhưng ngắn gọn:
- không có hỗ trợ thích hợp cho NULL (bạn chuyển đổi chúng thành '');
- không phân định tên bảng một cách nhất quán;
- sử dụng dấu ngoặc kép không ANSI làm dấu phân cách chuỗi;
- sử dụng truy vấn có bộ đệm trên các bảng lớn sẽ phá vỡ giới hạn bộ nhớ tối đa của PHP;
- việc nối tất cả các hàng cho một bảng lớn sẽ phá vỡ giới hạn bộ nhớ tối đa của PHP;
- sử dụng dấu gạch chéo () thay vì PDO ::quote ();
- chỉ kiểm tra các lỗi truy vấn ở cuối hàm;
- không kiểm tra việc tạo tệp không thành công;
- phần mở rộng gzip có thể không được tải
- Ngoài ra, có thể vẫn không hỗ trợ dữ liệu UTF8.
Đúng, cái này hay hơn kịch bản gốc của David Walsh. :-)
NULL không giống với '' trong SQL (ngoại trừ trong Oracle, nhưng chúng không tuân thủ tiêu chuẩn SQL trong trường hợp này). Xem MySQL, tốt hơn nên chèn NULL hoặc trống chuỗi?
Tôi đọc sai mã về vấn đề giới hạn bộ nhớ. Bạn đang viết đầu ra cho mỗi hàng, vì vậy điều đó không sao (trừ khi hàng chứa một đốm màu 1GB hoặc thứ gì đó).
Nhưng bạn không nên chỉ xuất một câu lệnh INSERT với một tập hợp các hàng được phân tách bằng dấu phẩy. Ngay cả mysqldump --extended-insert
xuất ra một độ dài dữ liệu hữu hạn, sau đó bắt đầu một câu lệnh INSERT mới. Tiêu chí là độ dài của câu lệnh INSERT có phù hợp với đối số tùy chọn cho --net-buffer-length
hay không .
Trong ANSI SQL, dấu ngoặc đơn '' được sử dụng để phân tách các ký tự chuỗi hoặc ký tự ngày tháng. Dấu ngoặc kép "" được sử dụng để phân tách các số nhận dạng như tên bảng hoặc tên cột. Theo mặc định, MySQL xử lý chúng như nhau, nhưng điều này không chuẩn. Xem Các cơ sở dữ liệu khác nhau có sử dụng các câu trích dẫn tên khác nhau không? . Nếu bạn cố gắng nhập dữ liệu sao lưu của mình trên máy chủ MySQL nơi bạn có SET SQL_MODE=ANSI_QUOTES
, quá trình nhập sẽ không thành công.
Ví dụ:query('SELECT * FROM '.$table);
và trên thực tế, mỗi trường hợp khác mà bạn sử dụng $ table trong một truy vấn. Bạn chỉ phân tách bảng một lần, trong câu lệnh INSERT, tập lệnh của bạn sẽ xuất ra.
MySQL luôn nhận ra dấu tích là dấu phân cách số nhận dạng và dấu ngoặc kép cho chuỗi / ngày. Nhưng dấu ngoặc kép thay đổi ý nghĩa tùy thuộc vào SQL_MODE mà tôi đã đề cập. Bạn không thể cho rằng SQL_MODE nào có hiệu lực trên phiên bản MySQL mà bạn khôi phục, vì vậy tốt nhất là bạn nên sử dụng dấu tích lùi cho số nhận dạng và dấu ngoặc đơn cho chuỗi. Lý do bạn phân tách chúng khi bạn truy vấn bảng của mình là bạn có thể có tên bảng là các từ dành riêng trong SQL hoặc chứa các ký tự đặc biệt, v.v.
Bạn có thể chèn tất cả các kiểu số mà không có dấu phân cách. Chỉ chuỗi và ngày mới cần dấu phân cách. Xem dev.mysql.com/doc/refman/5.6/en/literals.html