I have a stored procedure that updates a user's balance and inserts a transaction log. I don't know why, but sometimes it doesn't update the users
table.
Stored Procedure Code
DELIMITER $$
USE `db_name`$$
DROP PROCEDURE IF EXISTS `update_balance`$$
CREATE DEFINER=`username`@`%` PROCEDURE `update_balance`
(IN balancechange INT,
IN userid INT,
IN tableName VARCHAR(100),
IN `type` INT,
IN description VARCHAR(1000) CHARSET utf8,
IN trans_id VARCHAR(150))
BEGIN
START TRANSACTION;
SET @tmp = (SELECT id FROM users WHERE id = userid FOR UPDATE);
UPDATE users SET gold = @gold := ((@oldbalance:=gold) + balancechange)
WHERE id = userid AND (gold + balancechange) >= 0;
SET @countRow = ROW_COUNT();
IF (@countRow > 0) THEN
SET @t1 =CONCAT("INSERT INTO ", tableName,
" (user_id, type, balance_change, old_balance, new_balance, description, trans_id)
values ('", userid, "', '", `type`, "', '", balancechange, "', '", @oldbalance, "', '", @gold, "', '", description, "', '", trans_id, "')");
PREPARE stmt3 FROM @t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
SELECT @oldbalance AS oldbalance , @gold AS gold,
balancechange, 0 AS result;
ELSEIF (balancechange = 0) THEN
SET @oldbalance = (SELECT gold FROM users WHERE id = userid LIMIT 1);
SET @t1 =CONCAT("INSERT INTO ", tableName,
" (user_id, type, balance_change, old_balance, new_balance, description, trans_id)
values ('", userid, "', '", `type`, "', '", 0, "', '", @oldbalance, "', '", @oldbalance, "', '", description, "', '", trans_id, "')");
PREPARE stmt3 FROM @t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
SELECT @oldbalance AS oldbalance , @oldbalance AS gold,
0 AS balancechange, 0 AS result;
ELSE
SET @oldbalance = (SELECT gold FROM users WHERE id = userid LIMIT 1);
SELECT @oldbalance AS oldbalance , @oldbalance AS gold,
0 AS balancechange, -1 AS result;
END IF;
COMMIT;
END$$
DELIMITER ;
Usage
CALL update_balance(1000, 123, 'user_transaction201806', 1, '{$desc}', '123456789')
The users
table is InnoDB, the user_transaction201806
is MyISAM.
Sometime the data for a user isn't updated in the users
table, but the data for a user is still added in the relevant transaction table (e.g. user_transaction201806
) with correct data.
Because the table containing the user's transactions is in myISAM format, the transaction cannot be rolled back.
Best Answer
MyISAM ignores all transaction semantics. Convert to InnoDB !
But maybe that does not answer the Question. The one MyISAM table seems to be merely an audit log.
Further head scratching....
Please provide the transaction log for the bad case.