MySQL数据库,详解异常捕获及处理(三)
示例2
对⽰例1进⾏优化。
创建表:
DROP TABLE IF EXISTS t_funds;
CREATE TABLE t_funds(
user_id INT PRIMARY KEY COMMENT '⽤户id',
available DECIMAL(10,2) NOT NULL DEFAULT 0 COMMENT '账户余额',
version INT DEFAULT 0 COMMENT '版本号,每次更新+1'
) COMMENT '⽤户账户表';
DROP TABLE IF EXISTS t_order;
CREATE TABLE t_order(
id int PRIMARY KEY AUTO_INCREMENT COMMENT '订单id',
price DECIMAL(10,2) NOT NULL DEFAULT 0 COMMENT '订单⾦额'
)COMMENT '订单表';
delete from t_funds;
/*插⼊⼀条数据,⽤户id为1001,余额为1000*/
INSERT INTO t_funds (user_id,available) VALUES (1001,1000);
创建存储过程:
/*删除存储过程*/
DROP PROCEDURE IF EXISTS proc4;
/*声明结束符为$*/
DELIMITER $
/*创建存储过程*/
CREATE PROCEDURE proc4(v_user_id int,v_price decimal(10,2),OUT v_msg varchar(64))
a:BEGIN
/*保存当前余额*/
DECLARE v_available DECIMAL(10,2);
/*保存版本号*/
DECLARE v_version INT DEFAULT 0;
/*保存影响的⾏数*/
DECLARE v_update_count INT DEFAULT 0;
/*1.查询余额,判断余额是否够*/
select a.available,a.version into v_available,v_version from
t_funds a where a.user_id = v_user_id;
if v_available<=v_price THEN
SET v_msg='账户余额不⾜!';
/*退出*/
LEAVE a;
END IF;
/*模拟耗时5秒*/
SELECT sleep(5);
/*2.余额减去price*/
SET v_available = v_available - v_price;
/*3.更新余额*/
START TRANSACTION;
UPDATE t_funds SET available = v_available WHERE user_id =
v_user_id AND version = v_version;
/*获取上⾯update影响⾏数*/
select ROW_COUNT() INTO v_update_count;
IF v_update_count=1 THEN
/*插⼊订单明细*/
INSERT INTO t_order (price) VALUES (v_price);
SET v_msg='下单成功!';
/*提交事务*/
COMMIT; ELSE
SET v_msg='下单失败,请重试!';
/*回滚事务*/
ROLLBACK;
END IF;
END $
/*结束符置为;*/
DELIMITER ;
ROW_COUNT()可以获取更新或插⼊后获取受影响⾏数。将受影响⾏数放在
v_update_count中。
然后根据v_update_count是否等于1判断更新是否成功,如果成功则记录订单
信息并提交事务,否则回滚事务。
验证结果:开启2个cmd窗⼝,连接mysql,执⾏下⾯操作:
use javacode2018;
CALL proc4(1001,100,@v_msg);
select @v_msg;
窗⼝1结果:
mysql> CALL proc4(1001,100,@v_msg);
+----------+
| sleep(5) |
+----------+
| 0 |
+----------+
1 row in set (5.00 sec)
Query OK, 0 rows affected (5.00 sec)
mysql> select @v_msg;
+---------------+
| @v_msg |
+---------------+
| 下单成功! |
+---------------+
1 row in set (0.00 sec)窗⼝2结果:
mysql> CALL proc4(1001,100,@v_msg);
+----------+
| sleep(5) |
+----------+
| 0 |
+----------+
1 row in set (5.00 sec)
Query OK, 0 rows affected (5.01 sec)
mysql> select @v_msg;
+-------------------------+
| @v_msg |
+-------------------------+
| 下单失败,请重试! |
+-------------------------+
1 row in set (0.00 sec)
可以看到第⼀个窗⼜下单成功了,窗⼜2下单失败了。
再看⼀下2个表的数据:
mysql> SELECT * FROM t_funds;
+---------+-----------+---------+
| user_id | available | version |
+---------+-----------+---------+
| 1001 | 900.00 | 0 |
+---------+-----------+---------+
1 row in set (0.00 sec)
mysql> SELECT * FROM t_order;
+----+--------+
| id | price |
+----+--------+
| 1 | 100.00 |
+----+--------+
1 row in set (0.00 sec)
也正常。总结
1. 异常分为Mysql内部异常和外部异常
2. 内部异常由mysql内部触发,外部异常是sql的执⾏结果和期望结果不⼀致导致的错误
3. sql内部异常捕获⽅式
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET hasSqlError=TRUE;
4. ROW_COUNT()可以获取mysql中insert或者update影响的⾏数
5. 掌握使⽤乐观锁(添加版本号)来解决并发修改数据可能出错的问题
6. begin end前⾯可以加标签,LEAVE 标签可以退出对应的begin end,可以使⽤这个
来实现return的效果
相关文章
- 从本体论开始说起——运营商关系图谱的构建及应用
- 如何成为一名数据科学家?
- 从未见过的堂兄杀了人,你的DNA是关键证据
- 20个安全可靠的免费数据源,各领域数据任你挑
- 20个安全可靠的免费数据源,各领域数据任你挑
- 阿里云李飞飞:All in Cloud时代,云原生数据库优势明显
- 基于Hadoop生态系统的一高性能数据存储格式CarbonData(性能篇)
- 大数据告诉你:10年漫威,到底有多少角色
- TigerGraph:实时图数据库助力金融风控升级
- Splunk利用Splunk Connected Experiences和Splunk Business Flow 扩大数据访问
- 大数据开发常见的9种数据分析手段
- 以免在景区看人,我爬了5W条全国景点门票数据...
- 【实战解析】基于HBase的大数据存储在京东的应用场景
- 数据科学家告诉你哪些计算机科学书籍是你应该看的
- Kafka作为大数据的核心技术,你了解多少?
- Spring Boot 整合 Redis 实现缓存操作
- 大数据学习必须掌握的五大核心技术有哪些?
- 基于Antlr在Apache Flink中实现监控规则DSL化的探索实践
- 甲骨文再次被Gartner评为分析型数据管理解决方案魔力象限领导者
- 爬取吴亦凡微博102118条转发数据,扒一扒流量的真假