How to Store MySQL Trigger exception / failure info into Table or in Variables

前端 未结 3 837
自闭症患者
自闭症患者 2021-01-21 11:35

I am stuck at somewhere and I need some help from you.

Scenario

I have two databases i.e., test_db1 and test_db2 and have users

相关标签:
3条回答
  • 2021-01-21 12:01

    I found a hack via DECLARE CONTINUE HANDLER and GET DIAGNOSTICS CONDITION, so just thought, I must share it here.

    Here's my complete final script which keeps backup (sync) for both databases users table what it means is that any update on test_db1 (which we may call it as a productionDB) will occur on test_db2 (which we may call it to as stagingDB):

    /*
    Create two databases:
        1. `test_db1`
        2. `test_db2`
    and execute below create *Table script* on both databases.
    after that execute *Triggers Script* on `test_db1` only..
    */
    
    /*
        TABLE STRUCTURE FOR `users`
    */
    
    DROP TABLE IF EXISTS `users`;
    CREATE TABLE IF NOT EXISTS `users` (
      `id` int(11) AUTO_INCREMENT NOT NULL,
      `name` varchar(30) NOT NULL,
      `age` int(11) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    /*
        TABLE STRUCTURE FOR `errors`
    */
    
    DROP TABLE IF EXISTS `errors`;
    CREATE TABLE IF NOT EXISTS `errors` (
      `id` int(11) AUTO_INCREMENT NOT NULL,
      `code` varchar(30) NOT NULL,
      `message` TEXT NOT NULL,
      `query_type` varchar(50) NOT NULL,
      `record_id` int(11) NOT NULL,
      `on_db` varchar(50) NOT NULL,
      `on_table` varchar(50) NOT NULL,
      `emailed` TINYINT DEFAULT 0,
      `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    /*
        TRIGGERS SCRIPTS FOR INSERT, UPDATE AND DELETE OPERATIONS
    */
    
    DELIMITER //
    
    -- TRIGGER FOR INSERT
    DROP TRIGGER IF EXISTS `test_db1_users_ai`;
    CREATE TRIGGER `test_db1_users_ai` AFTER INSERT ON `users` FOR EACH ROW 
    BEGIN
        -- Declare variables to hold diagnostics area information
        DECLARE errorCode CHAR(5) DEFAULT '00000';
        DECLARE errorMessage TEXT DEFAULT '';
    
        -- Declare exception handler for failed insert
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
        BEGIN
          GET DIAGNOSTICS CONDITION 1
            errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
        END;
    
        -- Perform the insert
        INSERT INTO `test_db2`.`users` (id, name, age) VALUES (NEW.id, NEW.name, NEW.age);
    
        -- Check whether the insert was successful
        IF errorCode != '00000' THEN
            INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'insert', NEW.id, 'test_db2', 'users');
        END IF;
    END; //
    
    -- TRIGGER FOR UPDATE
    DROP TRIGGER IF EXISTS `test_db1_users_au`;
    CREATE TRIGGER `test_db1_users_au` AFTER UPDATE ON `users` FOR EACH ROW 
    BEGIN
        -- Declare variables to hold diagnostics area information
        DECLARE errorCode CHAR(5) DEFAULT '00000';
        DECLARE errorMessage TEXT DEFAULT '';
    
        -- Declare exception handler for failed insert
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
        BEGIN
          GET DIAGNOSTICS CONDITION 1
            errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
        END;
    
        -- Perform the update
        UPDATE `test_db2`.`users`
            SET name = NEW.name,
                age = NEW.age
            WHERE id = NEW.id;
    
        -- Check whether the update was successful
        IF errorCode != '00000' THEN
            INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'update', NEW.id, 'test_db2', 'users');
        END IF;
    END; //
    
    -- TRIGGER FOR DELETE
    DROP TRIGGER IF EXISTS `test_db1_users_ad`;
    CREATE TRIGGER `test_db1_users_ad` AFTER DELETE ON `users` FOR EACH ROW 
    BEGIN
        -- Declare variables to hold diagnostics area information
        DECLARE errorCode CHAR(5) DEFAULT '00000';
        DECLARE errorMessage TEXT DEFAULT '';
    
        -- Declare exception handler for failed insert
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
        BEGIN
          GET DIAGNOSTICS CONDITION 1
            errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
        END;
    
        -- Perform the delete
        DELETE FROM `test_db2`.`users`
            WHERE id = OLD.id;
    
        -- Check whether the insert was successful
        IF errorCode != '00000' THEN
            INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'delete', OLD.id, 'test_db2', 'users');
        END IF;
    END; //
    
    -- DELIMITER;
    

    Hope this will help others when they come over here.

    Cheers,

    0 讨论(0)
  • 2021-01-21 12:04

    Check out the syntax for DECLARE HANDLER

    http://dev.mysql.com/doc/refman/5.1/en/declare-handler.html

    Also, if you're trying to debug a SP, this might be helpful for you:

    http://www.bluegecko.net/mysql/debugging-stored-procedures/

    Upon trigger you can use something like below :

        CREATE TRIGGER `my_table_AINS` AFTER INSERT ON `my_table` FOR EACH ROW
    BEGIN
        DECLARE EXIT HANDLER FOR SQLEXCEPTION
            RESIGNAL;
        DECLARE EXIT HANDLER FOR SQLWARNING
            RESIGNAL;
        DECLARE EXIT HANDLER FOR NOT FOUND
            RESIGNAL; 
        -- Do the work of the trigger.
    END
    

    Hope this may help you.

    0 讨论(0)
  • 2021-01-21 12:27

    This looks like Master and Slave server/DB scenario. You can look into Binary Logging. So, any manipulation in Master server will be recorded as an event and same gets applied to slave server. Checkout MySQL official reference

    0 讨论(0)
提交回复
热议问题