转账日志表user_balance_log:

CREATE TABLE `user_balance_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '用户ID',
  `log_type` tinyint(4) NOT NULL COMMENT '日志类型1代表充值 2代表消费 3代表转账',
  `log_des` varchar(200) DEFAULT NULL COMMENT '日志备注',
  `log_value` decimal(10,2) NOT NULL COMMENT '金额发生值可以为负',
  `log_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

用户充值的步骤:

1、往日志表里面插入记录,插入成功后;

2、更新余额表的值,余额表里面需要判断当前ID是否存在;

3、如果存在则UPDATE 否则 INSERT。

DROP PROCEDURE IF EXISTS `sp_add_usermoney`;

CREATE DEFINER = CURRENT_USER PROCEDURE `sp_add_usermoney`(IN _user_id int,IN _log_type tinyint,IN _log_des varchar(200),IN _log_value decimal(10,2))
BEGIN
  DECLARE _error INT DEFAULT 0;
  DECLARE usercount INT DEFAULT 0;
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET _error = 1; 
  START TRANSACTION;

  # 插入用户充值日志表 
  INSERT INTO user_balance_log(user_id, log_type, log_des, log_value) VALUES (_user_id, _log_type, _log_des, _log_value);

  # 代表日志表插入成功
  IF ROW_COUNT() > 0 THEN 
      #判断用户余额表是否存在用户
      SELECT count(*) INTO usercount FROM user_balance WHERE user_id=_user_id;

      # 代表已经存在用户
      IF usercount > 0 THEN 
           UPDATE user_balance SET user_money = user_money + _log_value WHERE user_id = _user_id;
      ELSE
           INSERT INTO user_balance(user_id, user_money) VALUES (_user_id, _log_value);
      END IF;
  END IF;

  #模拟服务器很卡 
  SELECT SLEEP(7), '卡顿结束';

  IF _error = 1 THEN
      ROLLBACK;
  ELSE
      COMMIT;
  END IF;
END;

调用示例:

call sp_add_usermoney(3, 1, '用户充值详情', 10)

7秒之后,出现了如下这些结果:


思考题

如果停顿的这7秒出现点什么的话,会怎么样?

这种情况实际上是非常常见的。接下来我们来举个例子演示:

1、运行我们的七秒存储过程:

call sp_add_usermoney(3, 1, '用户充值详情', 10)

新建一个会话,并且迅速在七秒之内往转账表插入一条数据:

INSERT INTO shop.user_balance(user_id, user_money) VALUES (3, 20);

INSERT INTO shop.user_balance(user_id, user_money) VALUES (3, 20);

INSERT INTO shop.user_balance(user_id, user_money) VALUES (3, 20);

按照我们存储过程的逻辑以及需求,如果已有用户存在,那么应该是叠加UPDATE的。那如果操作的过程中有其它会话介入影响了呢?就会出现这种情况:

results matching ""

    No results matching ""