MST

星途 面试题库

面试题:MySQL存储过程中的事务与异常处理

假设有两个表:accounts(账户表,包含account_id, balance字段)和transactions(交易表,包含transaction_id, from_account_id, to_account_id, amount字段)。编写一个MySQL存储过程实现从一个账户向另一个账户转账的功能。要求使用事务确保转账操作的原子性,并且在出现错误(如账户余额不足、无效账户ID等)时能够正确回滚事务并抛出合适的异常信息,同时记录异常日志到一个单独的表error_logs(包含error_id, error_message, error_time字段)。
42.7万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试
DELIMITER //

CREATE PROCEDURE transfer_funds(
    IN from_account INT,
    IN to_account INT,
    IN transfer_amount DECIMAL(10, 2)
)
BEGIN
    DECLARE current_balance DECIMAL(10, 2);
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        -- 回滚事务
        ROLLBACK;
        -- 记录错误日志
        INSERT INTO error_logs (error_message, error_time)
        VALUES (CONCAT('转账失败,错误信息:', SQLERRM), NOW());
        -- 抛出异常
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = '转账操作出现错误,已回滚';
    END;

    -- 开启事务
    START TRANSACTION;

    -- 检查转出账户是否存在
    IF NOT EXISTS (SELECT 1 FROM accounts WHERE account_id = from_account) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = '转出账户ID无效';
    END IF;

    -- 检查转入账户是否存在
    IF NOT EXISTS (SELECT 1 FROM accounts WHERE account_id = to_account) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = '转入账户ID无效';
    END IF;

    -- 获取转出账户余额
    SELECT balance INTO current_balance FROM accounts WHERE account_id = from_account;

    -- 检查余额是否充足
    IF current_balance < transfer_amount THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = '转出账户余额不足';
    END IF;

    -- 更新转出账户余额
    UPDATE accounts
    SET balance = balance - transfer_amount
    WHERE account_id = from_account;

    -- 更新转入账户余额
    UPDATE accounts
    SET balance = balance + transfer_amount
    WHERE account_id = to_account;

    -- 插入交易记录
    INSERT INTO transactions (from_account_id, to_account_id, amount)
    VALUES (from_account, to_account, transfer_amount);

    -- 提交事务
    COMMIT;
END //

DELIMITER ;
  1. 存储过程定义
    • CREATE PROCEDURE transfer_funds定义了一个名为transfer_funds的存储过程,接受三个参数:from_account(转出账户ID),to_account(转入账户ID),transfer_amount(转账金额)。
  2. 异常处理
    • DECLARE EXIT HANDLER FOR SQLEXCEPTION定义了一个异常处理程序,当出现SQL异常时,它会执行以下操作:
      • 回滚事务,确保数据一致性。
      • error_logs表插入错误信息和当前时间。
      • 抛出一个自定义异常,提示转账操作出现错误。
  3. 事务处理
    • START TRANSACTION开启一个事务。
    • 一系列的IF语句检查转出账户和转入账户是否存在,以及转出账户余额是否充足。如果任何一个条件不满足,就抛出异常,触发异常处理程序。
    • 满足条件后,更新转出账户和转入账户的余额,并插入一条交易记录。
    • 最后COMMIT提交事务,确保所有操作的原子性。