数据库同时更新问题

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

Netkiller MySQL 手札

MySQL MariaDB...

MrNeo Chan陈景峰(BG7NYT)


中国广东省深圳市龙华新区民治街道溪山美地
518131
+86 13113668890
+86 755 29812080

文档始创于2010-11-18

版权 © 2011, 2012, 2013 Netkiller(Neo Chan). All rights reserved.

版权声明

转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。

文档出处:
http://netkiller.github.io
http://netkiller.sourceforge.net

 

$Date: 2013-04-10 15:03:49 +0800 (Wed, 10 Apr 2013) $

 

8.2.3. 解决更新冲突

CREATE TABLE `account` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`user` VARCHAR(50) NOT NULL DEFAULT '0',
	`cash` FLOAT NOT NULL DEFAULT '0',
	`point` INT(10) UNSIGNED NOT NULL DEFAULT '0',
	PRIMARY KEY (`id`),
	UNIQUE INDEX `user` (`user`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
		
INSERT INTO `test`.`account` (`user`, `cash`,`point`) VALUES ('neo', 10,10);
		

下面通过account表,我来模拟一个返点场景,例如电商网站经常会用到“返点”,购买一定数量的商品赠送一定的点数,可以通过点数买东西,这样涉及到点的加于减操作。

表 8.1. 更新丢失演示

Session A Session B
select point into @point from account where user='neo';
					
 
 
select point into @point from account where user='neo';
					
update account set point=@point+20 where user='neo';
					
 
 
update account set point=@point+50 where user='neo';
					

 

看看最后用户有多少点?

		
mysql> select point from account where user='neo';
+-------+
| point |
+-------+
|    30 |
+-------+
1 row in set (0.00 sec)
		
		

傻了吧,老板发火,测试不能重现,运维说这是程序计算错误,程序员说程序没有错误,这样的场景国内很多公司都出现过吧?

问题出在哪里呢?出在并发上,很多web程序员很少考虑并发是产生的问题,怎么解决?很多方案,在我的职业生涯过程就见过很多奇葩方案,都能解决问题但不太完美。

如果更新语句改为 update account set point=@point+50 where user='neo' and point=@point; 会更保险,但仍然不能解决同意时间所产生的更新操作

下面是通过事务与锁彻底解决上面的问题。

表 8.2. 防止更新丢失加锁演示

Session A Session B
begin;
select point into @point from account where user='neo' for update;
					
 
 
begin;
select point into @point from account where user='neo' for update;
					

执行到此处会挂起

update account set point=@point+20 where user='neo';
commit;
					
 
 
update account set point=@point+50 where user='neo';
commit;
					

 

上面解决更新覆盖问题,但从数据库设计角度是不应该这样设计表的。仅供参考

CREATE TABLE `account` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`user` VARCHAR(50) NOT NULL DEFAULT '0',
	`cash` FLOAT NOT NULL DEFAULT '0',
	`point` INT(10) NOT NULL DEFAULT '0',
	PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
		

每一次数据变化新增一条数据

INSERT INTO `test`.`account` (`user`, `point`) VALUES ('neo', -10);
INSERT INTO `test`.`account` (`user`, `point`) VALUES ('neo', -5);
INSERT INTO `test`.`account` (`user`, `point`) VALUES ('neo', 30);
INSERT INTO `test`.`account` (`user`, `point`) VALUES ('neo', -20);
		

计算剩余点数

select sum(point) as point from account where user='neo';
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7天前
|
存储 监控 安全
数据库数据的保密性
【4月更文挑战第9天】数据库保密性关键在于限制未授权访问和保护数据不泄露。措施包括访问控制、加密、数据脱敏、备份恢复、审计监控及安全配置等,确保数据安全和用户隐私。
21 2
|
存储 SQL 数据库
数据库实验一:数据库与数据表定义(1)—— 数据库相关操作
修改服务器默认存储位置:右键点击服务器,选择属性中的数据库设置,修改数据和日志存放位置后点击确定
151 0
数据库实验一:数据库与数据表定义(1)—— 数据库相关操作
|
3月前
|
SQL 数据库
数据库修改表
数据库修改表
32 0
|
5月前
|
JSON 小程序 API
开发-3-本地-数据库-查询-删除
开发-3-本地-数据库-查询-删除
32 0
|
7月前
|
SQL 关系型数据库 MySQL
数据库相关操作
数据库相关操作
|
8月前
|
SQL 缓存 关系型数据库
QxOrm操作数据库
我们在QT应用开发专栏中对数据库操作做了基本的介绍,很多程序员对于数据库的语法并不是很熟悉,我们就需要使用ORM库来弥补该方面的不足
146 0
|
存储 数据库
数据库中的表操作
数据库中的表操作
75 0
|
SQL 存储 JavaScript
数据库一些问题记录
视图 视图是一种虚拟表(虚表)。它基于一张表或多张表(原表)的查询结果。
90 0
数据库一些问题记录
|
数据库
Mogo数据库的简单操作
Mogo数据库的简单操作
231 0
|
数据库 开发工具 git