2011-10-30 41 views
27

Tôi đã nhầm lẫn với một khái niệm dường như đơn giản. Mysql định nghĩa chức năng xác định là một hàm màChức năng xác định trong mysql

luôn tạo ra kết quả tương tự cho đầu vào cùng một thông số

Vì vậy, trong sự hiểu biết của tôi, các chức năng như

CREATE FUNCTION foo (val INT) READS SQL DATA 
BEGIN 
    DECLARE retval INT; 
    SET retval = (SELECT COUNT(*) FROM table_1 WHERE field_1 = val); 
    RETURN retval; 
END; 

là không xác định (có không đảm bảo rằng việc xóa/cập nhật/chèn không xảy ra giữa 2 cuộc gọi đến chức năng). Đồng thời, tôi đã thấy nhiều hàm hoạt động khá giống nhau, tức là giá trị trả về dựa trên kết quả truy vấn và được khai báo là DETERMINISTIC. Có vẻ như tôi đang thiếu một cái gì đó rất cơ bản.

Có ai có thể làm rõ vấn đề này không?

Cảm ơn.

Cập nhật Cảm ơn những người đã trả lời (+1); cho đến nay có vẻ như lạm dụng rộng rãi từ khóa DETERMINISTIC. Vẫn rất khó tin với tôi rằng có quá nhiều người làm điều đó, vì vậy tôi sẽ chờ một chút cho các câu trả lời khác.

+0

Bạn có thể nêu một ví dụ về "nhiều chức năng" mà bạn đang nói đến không? – Mat

+0

@Mat: Ví dụ: http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html (trong phần nhận xét của người dùng, tìm kiếm "CREATE FUNCTION db.fnfullname" - nó đọc hàng từ db cho một id được trả về và giá trị trả về dựa trên kết quả của việc chọn). – a1ex07

+0

"... nhận xét của người dùng ..." ... Một số chức năng mysql thực mà bạn có trong đầu? – Mat

Trả lời

14

Từ MySQL 5.0 Tham khảo:

Đánh giá về bản chất của một thói quen được dựa trên “trung thực” của tác giả: MySQL không kiểm tra rằng một thói quen tuyên bố xác định là miễn phí các báo cáo sản xuất không xác định các kết quả. Tuy nhiên, việc xác định sai một thói quen có thể ảnh hưởng đến kết quả hoặc ảnh hưởng đến hiệu suất. Khai báo một thói quen không xác định như là DETERMINISTIC có thể dẫn đến kết quả không mong muốn bằng cách làm cho trình tối ưu hóa đưa ra các lựa chọn kế hoạch thực hiện không chính xác. Việc khai báo một thường trình xác định là NONDETERMINISTIC có thể làm giảm hiệu suất bằng cách khiến các tối ưu hóa có sẵn không được sử dụng. Trước MySQL 5.0.44, đặc tính DETERMINISTIC được chấp nhận, nhưng không được sử dụng bởi trình tối ưu hóa.

Vì vậy, bạn có nó, bạn có thể gắn thẻ thói quen được lưu trữ là DETERMINISTIC ngay cả khi không, nhưng có thể dẫn đến kết quả không mong muốn hoặc các vấn đề về hiệu suất.

+3

Vì vậy, chúng tôi có thể luôn có 50% cơ hội chọn sai? Tuyệt quá. lol Cảm nhận của bạn đã giúp tôi hiểu thêm một chút. – Cesar

+0

Trong "Mô hình tập hợp lồng nhau", ví dụ: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ Tôi đang sử dụng các thủ tục để chèn và xóa các nút. 1) Chúng ta có thể xem xét cập nhật tất cả các ranh giới của các nút (thêm 2 vào ranh giới thực tế) ở bên phải (sau) điểm chèn (nút chọn làm tham chiếu) là DETERMINISTIC? 2) Vì vậy, phá hủy một nút quá? 3) Di chuyển một nút ở bên trái của vị trí thực tế của nó? 4) Di chuyển một nút bên phải của vị trí thực tế của nó? – llange

+0

Tại sao tính năng đó? Có thể biên dịch nhanh hơn nếu một hàm thực sự xác định như '3 + x = output'? –

2

Bạn không thiếu gì cả. Hàm này không xác định. Tuyên bố nó xác định sẽ không làm cho cơ sở dữ liệu của bạn tan chảy nhưng nó có thể ảnh hưởng đến hiệu suất. From the MySQL site: "Việc khai báo một quy trình không xác định là DETERMINISTIC có thể dẫn đến kết quả không mong muốn bằng cách khiến trình tối ưu hóa đưa ra các lựa chọn kế hoạch thực hiện không đúng." Nhưng MySQL không thực thi hoặc kiểm tra nếu thói quen xác định được khai báo của bạn thực sự là xác định --- MySQL tin tưởng rằng bạn biết những gì bạn đang làm.

+1

Thường trình này là xác định bởi vì nếu bạn thực hiện thói quen này trên hai cơ sở dữ liệu giống nhau thì kết quả sẽ luôn giống nhau. – bikeman868

8

Kết quả DETERMINISTIC không đề cập đến các tập kết quả khác nhau được trả về vào các thời điểm khác nhau (tùy thuộc vào dữ liệu nào đã được thêm vào trong thời gian trung bình). Hơn nữa nó là một tham chiếu đến các tập kết quả trên các máy khác nhau bằng cách sử dụng cùng một dữ liệu. Ví dụ, nếu bạn có 2 máy chạy một hàm bao gồm uuid() hoặc tham chiếu các biến máy chủ thì những máy này sẽ được coi là KHÔNG XÁC ĐỊNH. Điều này là hữu ích ví dụ trong nhân rộng bởi vì các cuộc gọi chức năng được lưu trữ trong bản ghi nhị phân (chủ) và sau đó cũng được thực hiện bởi các nô lệ. Để biết chi tiết và ví dụ, hãy xem http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

Việc sử dụng DETERMINISTIC do đó (99% thời gian) chính xác, không được coi là lạm dụng.

+0

Từ mysql: 'Một thường trình được coi là "xác định" nếu nó luôn tạo ra cùng một kết quả cho cùng các tham số đầu vào, và "không xác định" nếu không.' Các định nghĩa về 'hàm xác định' từ các nguồn khác cũng có "luôn trả về cùng một kết quả cho cùng một tham số". Sử dụng DML nhất định (ít nhất là SELECT) là một hoạt động hoàn toàn hợp lệ bên trong phần thân của hàm. Nếu bạn nói nó không đề cập đến các tập kết quả khác nhau, thì tất cả các định nghĩa đều sai vì 'luôn luôn' ngụ ý tất cả các câu lệnh hợp lệ có thể có trong cơ thể hàm. – a1ex07

+0

"tạo ra cùng một kết quả" có nghĩa là tạo ra cùng một kết quả trong cơ sở dữ liệu. Nó không có nghĩa là trả về cùng một tập kết quả. Tại sao MySQL lại quan tâm nếu tập kết quả khác nhau mỗi lần hay không? Nó không quan tâm tuy nhiên nếu kết quả được lưu trữ dữ liệu là khác nhau - xem câu trả lời của tôi để biết thêm chi tiết. – bikeman868

+0

Tôi đánh giá cao câu trả lời của Jon Gilbert và bikeman868 ... Tôi ước rằng có một số nguồn chính thức sẽ hỗ trợ họ. [Câu trả lời dba.stackexchange.com này] (https://dba.stackexchange.com/questions/4079/mysql-deterministic-procedures/4080#4080) bởi một người có đại diện 23k đưa ra câu trả lời ngược lại. –

0

Xác định là quan trọng nếu bạn đã bật tính năng sao chép hoặc có thể sử dụng nó một ngày. Một cuộc gọi hàm không xác định gây ra một thay đổi hàng (cập nhật hoặc chèn) ví dụ sẽ cần phải được nhân rộng bằng cách sử dụng nhị phân (dựa trên hàng) trong đó như một hàm xác định có thể được nhân rộng dựa trên câu lệnh. Điều này trở nên thú vị khi xem các ví dụ SQL của bạn ở trên, cái nào sẽ xảy ra giống nhau (cho cùng một kết quả) khi được nhân bản bằng cách sử dụng câu lệnh, và cần được nhân rộng bằng kết quả thu được trong bản gốc (dựa trên hàng). Nếu các câu lệnh được thực hiện với khóa thích hợp và có thể được đảm bảo thực hiện theo cùng thứ tự trên Slave thì chúng thực sự là xác định. Nếu lệnh khóa/lệnh mà Slave sử dụng (không đồng thời, xử lý nối tiếp các câu lệnh theo thứ tự chúng được bắt đầu) có nghĩa là câu trả lời có thể khác nhau, thì hàm sẽ không xác định.

3

Tôi nghĩ rằng thói quen của bạn là xác định. Tài liệu này không rõ ràng và điều này đã dẫn đến nhiều người đang rất bối rối về vấn đề này, mà thực sự là nhiều về nhân rộng hơn bất cứ điều gì khác.

Xem xét tình huống mà bạn đã thiết lập sao chép giữa hai cơ sở dữ liệu. Cơ sở dữ liệu chủ lưu giữ nhật ký của tất cả các thường trình được lưu trữ đã được thực thi bao gồm các tham số đầu vào của chúng và gửi nhật ký này tới slave. Các nô lệ thực thi cùng một thói quen được lưu trữ trong cùng một thứ tự với các tham số đầu vào tương tự. Cơ sở dữ liệu nô lệ bây giờ có chứa dữ liệu giống hệt với cơ sở dữ liệu chủ không? Nếu thói quen được lưu trữ tạo GUID và lưu trữ chúng trong cơ sở dữ liệu thì không, cơ sở dữ liệu chủ và nô lệ sẽ khác và sao chép sẽ bị hỏng.

Mục đích chính của cờ DETERMINISTIC là nói cho MySQL biết liệu có bao gồm các cuộc gọi đến thường trình lưu trữ này trong nhật ký sao chép sẽ dẫn đến sự khác biệt giữa cơ sở dữ liệu chủ và nô lệ nhân bản.

Khi quyết định cờ DETERMINISTIC có phù hợp với thói quen lưu trữ như sau: Nếu tôi bắt đầu với hai cơ sở dữ liệu giống nhau và tôi thực hiện thường trình trên cả hai cơ sở dữ liệu với cùng tham số đầu vào thì cơ sở dữ liệu của tôi vẫn giống nhau? Nếu họ là sau đó thói quen của tôi là xác định.

Nếu bạn khai báo thường trình xác định khi không, thì bản sao của cơ sở dữ liệu chính của bạn có thể không giống với bản gốc vì MySQL sẽ chỉ thêm lời gọi thủ tục vào nhật ký sao chép và thực hiện quy trình trên slave không tạo ra kết quả giống hệt nhau.

Nếu thường trình của bạn không xác định thì MySQL phải bao gồm các hàng bị ảnh hưởng trong nhật ký sao chép thay thế. Nếu bạn khai báo thường trình của bạn như là không xác định khi nó không phải là điều này sẽ không phá vỡ bất cứ điều gì, nhưng bản ghi nhân rộng sẽ chứa tất cả các hàng bị ảnh hưởng khi cuộc gọi thủ tục là đủ và điều này có thể ảnh hưởng đến hiệu suất.

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