MST

星途 面试题库

面试题:MySQL用户自定义函数开发之实战优化与事务处理

在一个电商数据库中,有订单表orders(包含order_id, user_id, order_amount等字段)和用户表users(包含user_id, credit等字段)。编写一个用户自定义函数,该函数实现当用户下订单时,根据订单金额更新用户的信用值(例如订单金额每100元,信用值加1),并且要保证在函数执行过程中数据的一致性,使用事务处理可能出现的异常情况,如订单金额为负数或者更新信用值失败等,同时阐述在高并发场景下如何优化此函数的性能。
17.4万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试
-- 创建函数
DELIMITER //
CREATE FUNCTION update_user_credit(new_order_amount DECIMAL(10, 2), user_id INT) RETURNS VARCHAR(50)
DETERMINISTIC
BEGIN
    DECLARE credit_increase INT;
    DECLARE credit_value DECIMAL(10, 2);
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        -- 捕获异常,回滚事务
        ROLLBACK;
        RETURN '操作失败';
    END;
    -- 检查订单金额是否为负数
    IF new_order_amount < 0 THEN
        RETURN '订单金额不能为负数';
    END IF;
    -- 计算信用值增加量
    SET credit_increase = FLOOR(new_order_amount / 100);
    -- 开启事务
    START TRANSACTION;
    -- 获取当前用户信用值
    SELECT credit INTO credit_value FROM users WHERE user_id = user_id;
    -- 更新用户信用值
    UPDATE users SET credit = credit_value + credit_increase WHERE user_id = user_id;
    -- 提交事务
    COMMIT;
    RETURN '操作成功';
END //
DELIMITER ;

高并发场景下性能优化阐述

  1. 使用行级锁:上述代码中,MySQL默认使用行级锁。通过对users表中特定user_id对应的行加锁,避免了其他事务同时对同一用户的信用值进行修改,减少锁争用,提高并发性能。
  2. 优化数据库结构:确保users表的user_id字段建立索引,这样在查询和更新用户信用值时能快速定位到对应行,减少查询时间,提高并发处理能力。
  3. 异步处理:将信用值更新操作放入消息队列(如RabbitMQ、Kafka等),订单创建成功后,发送消息到队列,由专门的消费者异步处理信用值更新。这样可以减少订单创建时的响应时间,提高系统整体并发性能。
  4. 缓存:使用缓存(如Redis)存储部分用户信用值信息,在更新信用值时,先更新缓存,然后异步批量更新数据库。读取信用值时,优先从缓存读取,减少数据库压力,提高并发性能。