Gọi một thủ tục được lưu trữ từ một kích hoạt


17

Tôi đã tạo một thủ tục được lưu trữ trong mysql bằng cú pháp sau.

DROP PROCEDURE IF EXISTS `sp-set_comment_count`;

DELIMITER $$

CREATE PROCEDURE `sp_set-comment_count` (IN _id INT)
BEGIN
   -- AC   - AllCount
   DECLARE AC INT DEFAULT 0;

   SELECT COUNT(*) AS ac
     INTO AC
     FROM usergroups AS ug
LEFT JOIN usergroup_comments AS ugm ON ugm.`gid` = ug.`id`
LEFT JOIN mediagallery AS dm ON ugm.mid = dm.`id`
    WHERE dm.`status` NOT IN (200, 201, 202, 203, 204, 205)
      AND ug.`id` = _id;

   UPDATE usergroups
      SET allCount = AC,
    WHERE usergroups.`id` = _id;

END $$
DELIMITER ;

FYI Tôi đã đơn giản hóa rất nhiều thủ tục được lưu trữ nhưng tôi biết nó hoạt động mà không có vấn đề gì.

Những gì tôi muốn có thể làm là thiết lập một trình kích hoạt từ usergroup_comments hoạt động như thế này.

DROP TRIGGER IF EXISTS `usergroups_comments_insert` 

CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
    FOR EACH ROW
    BEGIN
       CALL sp-set-comment_count(NEW.`gid`);
    END;

Nhưng vì một số lý do, mỗi lần tôi làm mysql lại đưa ra một lỗi với tôi, điều đó không hữu ích lắm khi nói rằng có lỗi cú pháp trên dòng 4.

Tôi đã xem qua tài liệu mysql và tìm thấy một số thông tin về các hạn chế của trình kích hoạt nhưng thấy nó khá phức tạp.

http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html

Bất kỳ ý tưởng sẽ hữu ích.


Vì vậy, hóa ra vấn đề với thủ tục được lưu trữ ở trên được gọi là thực tế là nó có dấu gạch nối trong tên của nó. Thay đổi tên thủ tục được lưu trữ thành sp_set_comment_count đã giải quyết vấn đề.
Đánh dấu

Câu trả lời:


24

Có lý do tuyệt vời tại sao bạn không bao giờ nên gọi các thủ tục được lưu trữ từ bên trong kích hoạt.

Triggers, về bản chất, thủ tục lưu trữ. Hành động của họ hầu như khó quay trở lại . Ngay cả khi tất cả các bảng bên dưới là InnoDB, bạn sẽ gặp một khối lượng khóa chia sẻ theo tỷ lệ và sự gián đoạn khó chịu từ các khóa hàng độc quyền. Đó sẽ là trường hợp nếu các trình kích hoạt đang thao túng các bảng với INSERT và CẬP NHẬT bị đình trệ để thực hiện MVCC nhiệm vụ nặng nề trong mỗi lệnh gọi đến trình kích hoạt .

Đừng quên rằng Triggers yêu cầu trên không. Trên thực tế, theo Lập trình thủ tục lưu trữ của MySQL , trang 256 dưới phần đầu "Trigger Overhead" có nội dung như sau:

Điều quan trọng cần nhớ là, do sự cần thiết, các trình kích hoạt sẽ thêm chi phí cho câu lệnh DML mà chúng áp dụng. lượng chi phí thực tế sẽ phụ thuộc vào bản chất của trình kích hoạt, nhưng --- vì tất cả các trình kích hoạt MySQL thực thi CHO MACHI ROW --- chi phí có thể nhanh chóng tích lũy cho các câu lệnh xử lý số lượng lớn hàng. Do đó, bạn nên tránh đặt bất kỳ câu lệnh SQL hoặc mã thủ tục đắt tiền nào trong các trình kích hoạt.

Một lời giải thích mở rộng về chi phí kích hoạt được đưa ra trên các trang 529-531. Điểm kết luận từ phần đó nêu sau:

Bài học ở đây là: vì mã kích hoạt sẽ thực thi một lần cho mỗi hàng bị ảnh hưởng bởi câu lệnh DML, nên trình kích hoạt có thể dễ dàng trở thành yếu tố quan trọng nhất trong hiệu suất DML. Mã bên trong thân trình kích hoạt cần phải nhẹ nhất có thể và - đặc biệt - mọi câu lệnh SQL trong trình kích hoạt phải được các chỉ mục hỗ trợ bất cứ khi nào có thể.

Tôi đã giải thích các khía cạnh khó chịu khác của Triggers trong một bài viết trước đó.

TÓM LƯỢC

Tôi thực sự khuyên bạn không nên gọi bất kỳ thủ tục được lưu trữ nào từ Trình kích hoạt , ngay cả khi MySQL cho phép. Bạn nên kiểm tra các hạn chế hiện tại đối với MySQL 5.5 .


Thú vị, cảm ơn cho những người đứng đầu. Việc thiếu các truy vấn giao dịch trong môi trường của chúng tôi sẽ giảm thiểu vấn đề giao dịch. Tuy nhiên tôi có thể đánh giá cao ý tưởng tích lũy trên đầu. Tôi đoán tôi sẽ xem db một lúc để xem kết quả của sự thay đổi này là gì.
Đánh dấu

Tôi không nghĩ rằng việc kết hợp các trình kích hoạt với các thủ tục được lưu trữ là chính xác. Tối thiểu, nó hợp lệ để bắt đầu và thực hiện giao dịch trong một thủ tục được lưu trữ. MySQL phàn nàn nếu bạn cố gắng làm điều tương tự trong một kích hoạt. Điều này thật ngớ ngẩn, bởi vì có một trình kích hoạt cần cập nhật giao dịch một hoặc nhiều bảng để đáp ứng với một số thay đổi là trường hợp sử dụng hoàn toàn hợp lệ cần được hỗ trợ theo cách đơn giản.
aroth

Vì vậy, tôi có kích hoạt này, đó là thực sự lớn. Nó thực hiện một số tính toán trên bảng của tôi, cả khi chèn và cập nhật. Kích hoạt trong Mysql thực sự có thể trở nên đau đớn khi chúng phức tạp. Nó sẽ dễ dàng hơn nhiều để phá vỡ kích hoạt thành các thủ tục.
Lamar

8

Vì vậy, hóa ra đây là vấn đề khiến tôi lo lắng trong vài giờ có tin hay không.

Tôi có thể dễ dàng xác định một thủ tục được gọi là sp_set-comment_count. Tuy nhiên, khi gọi thủ tục nói, nó không hoạt động theo cùng một cách.

CALL sp_set-comment_count (Tôi chỉ có thể giả sử điều này là do máy chủ diễn giải - như một điểm trừ).

Tôi đã thay đổi tên thủ tục được lưu trữ thành chỉ sử dụng dấu gạch dưới và dường như nó đã giải quyết mọi thứ.


Đến bữa tiệc muộn nhưng: bạn đã tạo SP của mình bằng cách sử dụng một mã định danh được trích dẫn, cho phép các ký tự đặc biệt trong tên của nó, vì vậy bạn nên tham chiếu nó tương tự ở nơi khác:CALL `sp-set-comment_count`(NEW.`gid`);
mustaccio

5

Nếu nó nói về lỗi cú pháp, rất có thể bạn đã quên thay đổi dấu phân cách (như bạn đã làm đối với thủ tục được lưu trữ). Vì vậy bạn cần

DELIMITER $$
CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
FOR EACH ROW
BEGIN
   CALL sp_set_count(NEW.`gid`);
END;
$$

Cảm ơn bạn điều này thực sự đã cho tôi suy nghĩ theo dõi đúng. Trong thực tế, sp của tôi được gọi là sp-set_comment_count. Khi được gọi bởi trình kích hoạt, có vẻ như vấn đề là khi gọi SP từ trình kích hoạt - tiếp tục ném lỗi.
Đánh dấu

1

Có vẻ như dấu phẩy sau AClà lỗi cú pháp:

UPDATE usergroups
   SET allCount = AC,
 WHERE ........

Điểm hợp lệ, nhưng không phải là nguyên nhân thực sự của lỗi trong trường hợp này. Tôi chỉ cắt bớt một số bộ bổ sung từ truy vấn đó và quên xóa,
Đánh dấu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.