2011-02-07 33 views
14

Cơ sở dữ liệu của chúng tôi có chức năng tạo số thứ tự. Nó đọc một giá trị từ một bảng Settings, tăng nó, sau đó trả về giá trị mới. Ví dụ:TẠO CHỨC NĂNG lỗi "Chức năng này không có DETERMINISTIC, NO SQL hoặc READS SQL DATA"

CREATE FUNCTION NextOrderNumber() RETURNS INTEGER UNSIGNED NOT DETERMINISTIC 
BEGIN 
    DECLARE number INTEGER UNSIGNED; 
    UPDATE Settings SET IntegerValue=LAST_INSERT_ID(IntegerValue+1) WHERE KeyName='NextOrderNumber'; 
    SET number=LAST_INSERT_ID(); 
    return number; 
END 

Lưu ý: Đừng phê bình chức năng này tôi biết nó có sai sót chỉ để minh hoạ.

Chúng tôi sử dụng chức năng này như sau:

INSERT INTO Orders(OrderNumber, ...) 
SELECT NextOrderNumber(), ... 

Khi đăng nhập nhị phân được kích hoạt, CREATE FUNCTION cho lỗi này:

This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)

Bất kể những gì binlog_format được thiết lập, có thực sự là một vấn đề với các chức năng trên? Theo đọc của tôi về các MySQL page có liên quan tôi không thể thấy bất kỳ lý do tại sao chức năng này sẽ không tương thích với nhân rộng, với một trong hai mức ghi nhật ký nhị phân ROW hoặc STATEMENT.

Nếu chức năng này an toàn, hãy đặt log_bin_trust_function_creators = 1 toàn cầu làm tôi khó chịu. Tôi không muốn vô hiệu hóa kiểm tra này cho tất cả các chức năng, chỉ cần một chức năng này. Thay vào đó, tôi có thể gắn cờ hàm này là NO SQL để chặn cảnh báo không? Tôi đã thử và nó đã hoạt động. Điều này có gây ra bất kỳ vấn đề nào không?

Trả lời

0

Hãy suy nghĩ về nội dung được ghi vào nhật ký nhị phân. Bạn không thể đảm bảo rằng một đơn đặt hàng được tạo trên máy chủ sẽ có cùng chuỗi được tạo cho nó khi giao dịch được phát trên nô lệ - hoặc, nhiều khả năng hơn, bởi một máy chủ khác trong cụm. ví dụ.

0) Node 1 and Node 2 are in sync, NextOrderNumber=100 
1) Node 1 receives insert statement wrt order from customer A and assigns 
    order number 100, changes its NextOrderNumber to 101 
2) Node 1 writes the settings update to the log 
3) Node 1 writes the insert statement to the log 
4) Node 2 processes for customer B, asigns order number 100 and increments 
5) Node 2 writes the settings update from to the log 
6) Node 2 writes the insert statement to the log 
7) Nodes 2 reads settings update from the log @2 
     - Its NextOrderNumber is now 102 
8) Node 2 reads insert from log @3, tries to apply it but it fails 
     due to duplicate key 
9) Node 1 reads the update @5 - Its nextOrderNumber is also now 102 
10) Node1 reads insert from log @6 - 
     but this fails due to duplicate key 

Bây giờ đơn đặt hàng 100 trên 2 nút tham khảo dữ liệu khác nhau, và không có lệnh 101.

Có một lý do rằng đã có rất nhiều tính năng bổ sung để sửa đổi hành vi của các biến auto_increment .

Nếu bạn quấn phần chèn vào trong quy trình - lấy giá trị từ trình tạo trình tự, sau đó nhúng nó vào câu lệnh chèn, vấn đề ngay lập tức sẽ được giải quyết, tuy nhiên bạn cần suy nghĩ về cách bạn tránh gán cùng một số hai lần bằng cách sử dụng các nút cơ sở dữ liệu khác nhau.

+0

symcbean - Tôi hiểu cách tiếp cận này không hoạt động trong một cụm. Tôi không hỏi về kịch bản đó. Tôi hỏi về thiết lập master-slave đơn giản, nơi chèn/cập nhật chỉ diễn ra ở một nơi. – richb

24

Tôi đã googled và tôi ở đây. Tôi đã tìm ra một cách:

SET GLOBAL log_bin_trust_function_creators = 1; 

Nhưng hãy cẩn thận, nó có thể không an toàn cho việc phục hồi dữ liệu hoặc sao chép ...

+8

Điều này không giải quyết được câu hỏi dưới bất kỳ hình thức nào. – richb

+0

@ richb nhưng nó hoạt động. –

5

Theo tôi understating nó gây ra vấn đề khi phục hồi dữ liệu hoặc sao chép

Tham khảo: http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

MySQL 5.0.6: Các câu lệnh tạo thói quen lưu trữ và câu lệnh CALL được ghi lại. Các lời gọi hàm được lưu trữ được ghi lại khi chúng xuất hiện trong các câu lệnh cập nhật dữ liệu (vì các câu lệnh đó được ghi lại).

Tuy nhiên, lời gọi hàm không được ghi lại khi chúng xuất hiện trong các câu lệnh như SELECT không thay đổi dữ liệu, ngay cả khi thay đổi dữ liệu xảy ra trong chính hàm; điều này có thể gây ra vấn đề.

Trong một số trường hợp, các chức năng và thủ tục có thể có hiệu ứng khác nhau nếu được thực hiện tại các thời điểm khác nhau hoặc trên các máy chủ (master và slave) khác nhau và do đó có thể không an toàn cho việc khôi phục hoặc sao chép dữ liệu.

Ví dụ:

CREATE FUNCTION myfunc() RETURNS INT DETERMINISTIC 
BEGIN 
    INSERT INTO t (i) VALUES(1); 
    RETURN 0; 
END; 

SELECT myfunc(); 

Nếu một chức năng lưu trữ được gọi trong một tuyên bố như CHỌN mà không sửa đổi dữ liệu, thực hiện các chức năng không ghi vào bản ghi nhị phân, ngay cả khi chức năng tự sửa đổi dữ liệu. Hành vi ghi nhật ký này có khả năng gây ra sự cố. Giả sử rằng một hàm myfunc() được định nghĩa như trên.

+0

Tôi không nghĩ điều này là chính xác. Nhìn vào [link] (https://dev.mysql.com/doc/refman/5.7/en/stored-programs-logging.html) bạn sẽ thấy _italics _... Đối với các hàm được lưu trữ, các thay đổi hàng được thực hiện trong hàm đã đăng nhập, không phải lời gọi hàm. Đối với trình kích hoạt, các thay đổi hàng do trình kích hoạt thực hiện được ghi lại. ... _chữ in nghiêng_ . Vì vậy, đó là với tôi không thể giải thích tại sao logbin_format = ROW vẫn xuất hiện để không cho phép các chức năng không được đánh dấu là DETERMINISTIC. –

-3

Execute này ngay trước khi tạo ra các chức năng:

SET @@global.log_bin_trust_function_creators = 1; 

Và thêm MODIFIES SQL DATA để khai báo.

Ngoài ra ... tốt, bạn đã yêu cầu không tự nhận xét chức năng, nhưng tôi khuyên bạn nên bỏ biến số number và chỉ cần thực hiện RETURN LAST_INSERT_ID().

+1

Điều này không hoạt động. log_bin_trust_function_creators là GLOBAL, không phải là biến phiên. – richb

+0

Xin lỗi, đó là lỗi đánh máy. Tôi đã chỉnh sửa câu trả lời của mình. –

+0

Huh? Hành vi toàn cầu không bị ảnh hưởng ?? Vâng. Bạn đang thiết lập một biến toàn cục. – richb

1

Có hai cách để sửa lỗi này:

Execute sau trong MySQL console:

SET GLOBAL log_bin_trust_function_creators = 1; 

Thêm dòng sau vào file cấu hình mysql.ini:

log_bin_trust_function_creators = 1 

Các thiết lập thư giãn việc kiểm tra các hàm không xác định. Hàm không xác định là các hàm sửa đổi dữ liệu (tức là có cập nhật, chèn hoặc xóa (các) câu lệnh). Để biết thêm thông tin, hãy xem tại đây.

Xin lưu ý, nếu tính năng ghi nhật ký nhị phân KHÔNG được bật, cài đặt này không áp dụng.

+0

i m phải đối mặt với lỗi này khi tôi chọn bảng từ chế độ xem. những gì có thể là giải pháp? – sat

0

Could I instead just flag the function as NO SQL to suppress the warning? I tried it and it worked. Will this cause any problem?

Theo Mysql doc này:

Assessment of the nature of a function is based on the “honesty” of the creator: MySQL does not check that a function declared DETERMINISTIC is free of statements that produce nondeterministic results.

Vì vậy, nó tùy thuộc vào bạn. Nếu bạn chắc chắn phương pháp sẽ không gây ra bất kỳ sự cố nào ...

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