多线程操作Mysql问题

lee_鹿游原 2015-03-28 10:45:14
这个存储过程,多线程下会丢失数据。

CREATE DEFINER=`root`@`%` PROCEDURE `game_register1`(IN `_status` int,IN `_account` varchar(64),IN `_password` varchar(64),IN `_platform` int)
BEGIN
#Routine body goes here...
DECLARE _id BIGINT;
SET _id = -1;
SELECT userid INTO _id FROM game_user.account WHERE account=_account AND platform=_platform;
IF _id < 0 THEN
INSERT INTO game_user.account(status,account,password,platform) SELECT _status,_account,_password,_platform FROM DUAL WHERE NOT EXISTS(SELECT * FROM game_user.account WHERE account=_account AND platform=_platform);
SELECT userid INTO _id FROM game_user.account WHERE account=_account AND platform=_platform;
IF LAST_INSERT_ID() = _id then
SELECT 1,_id;
ELSE
SELECT -2;
END IF;
ELSE
SELECT -1;
END IF;
END
;;

昨天经过测试,问题出在 : INSERT INTO game_user.account(status,account,password,platform) SELECT _status,_account,_password,_platform FROM DUAL WHERE NOT EXISTS(SELECT * FROM game_user.account WHERE account=_account AND platform=_platform);
WHERE NOT EXISTS(SELECT * FROM game_user.account WHERE account=_account AND platform=_platform); 去掉这部分代码,数据不会丢失,前者数据会丢失。
不太理解为何会出现这种状况 ,希望能帮忙分析下。
...全文
381 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tiger_Zhao 2015-04-03
  • 打赏
  • 举报
回复
从数据库上是没有错的,所以只能是代码编写的逻辑和你预期不同。
lee_鹿游原 2015-04-03
  • 打赏
  • 举报
回复
引用 3 楼 Tiger_Zhao 的回复:
按你代码的逻辑这是正常的表现啊: (1)如果A、B两个会话并发,用相同的 _account、_platform 调用这个存储过程; (2)并且第一个SELECT都取得了 _id=-1 的结果,“一起”调用INSERT; (3)数据库还是会给两个INSERT操作排队的,假设A争先,插入了一条 id=10 的记录,并且通过 SELECT 1,_id 返回结果10,结束事物; (4)这下轮到B,因为已经有 id=10 的记录,被 NOT EXISTS 排出,所以实际没有插入记录,但是照样可以取到 _id=10,并且通过 SELECT 1,_id 返回结果一样是10。 这样只插入一条记录,A、B都返回同一个id。 假如去掉 NOT EXISTS,步骤(4)B会插入 id=11 的记录,返回的也是11。 两个会话会查如两条。 你到底需要哪个逻辑?
这个问题,最后我在调用存储过程 函数外,加锁了。 防止多线程同时调用存储过程... 数据保证正常。 之前是多线程调用,mysql没有报任何错误日志,而且调用这个存储过程会丢失数据,纠结其丢失原因。
Tiger_Zhao 2015-04-02
  • 打赏
  • 举报
回复
假如 LAST_INSERT_ID() 是会话直接独立的话,(4)走的应该是 SELECT -2。
Tiger_Zhao 2015-04-02
  • 打赏
  • 举报
回复
按你代码的逻辑这是正常的表现啊:
(1)如果A、B两个会话并发,用相同的 _account、_platform 调用这个存储过程;
(2)并且第一个SELECT都取得了 _id=-1 的结果,“一起”调用INSERT;
(3)数据库还是会给两个INSERT操作排队的,假设A争先,插入了一条 id=10 的记录,并且通过 SELECT 1,_id 返回结果10,结束事物;
(4)这下轮到B,因为已经有 id=10 的记录,被 NOT EXISTS 排出,所以实际没有插入记录,但是照样可以取到 _id=10,并且通过 SELECT 1,_id 返回结果一样是10。
这样只插入一条记录,A、B都返回同一个id。

假如去掉 NOT EXISTS,步骤(4)B会插入 id=11 的记录,返回的也是11。
两个会话会查如两条。

你到底需要哪个逻辑?
LongRui888 2015-04-02
  • 打赏
  • 举报
回复
是mysql的问题, WHERE NOT EXISTS(SELECT * FROM game_user.account WHERE account=_account AND platform=_platform); 这个应该是判断如果当前要插入的值,如果不存在于 game_user.account 表中,那么就插入,判断的时候根据 账户和 平台。
贫下码农 2015-04-02
  • 打赏
  • 举报
回复
你这问题到底是 mysql 还是 mssql
内容概要:本文系统研究了构网型变流器的正负序阻抗解耦特性及其在弱电网环境下的稳定性表现,重点依托Matlab/Simulink仿真平台,构建了详细的阻抗数学模型,设计了解耦控制策略,并采用小信号扫频法进行频域辨识与稳定性验证。研究深入探讨了构网型变流器与传统跟网型逆变器在正负序阻抗特性上的本质差异,结合虚拟同步发电机(VSG)等先进控制技术,分析其在抑制宽频带振荡、削弱锁相环动态耦合等方面的优越性。文中不仅提供了完整的仿真模型与MATLAB代码实现,还整合了光伏、风电、储能、微电网等多类新能源系统的阻抗建模与稳定性分析资源,形成了一套面向新型电力系统稳定性的综合性技术资料体系,具有较强的科研复现与工程参考价值。; 适合人群:面向具备电力电子、电力系统自动化、新能源并网等专业背景的研究生、高校教师及工程技术人员,特别适用于从事阻抗建模、小干扰稳定性分析、宽频振荡机理研究以及撰写高水平学术论文的科研工作者。; 使用场景及目标:①掌握构网型变流器正负序阻抗建模与扫频辨识的仿真方法;②深入理解VSG等构网型控制在弱电网中提升稳定性的内在机理;③复现顶刊论文中的阻抗分析流程与稳定性判据应用;④利用提供的成熟模型与代码加速科研进程,支撑课题研究与学术成果产出。; 阅读建议:建议结合文中提供的Simulink模型与MATLAB代码,按照“理论建模—仿真搭建—扫频激励—频响提取—Nyquist判据分析”的完整流程进行实践操作,重点关注扫频信号的注入方式、频率范围设置及阻抗曲线的物理意义解读,并参考博士论文复现案例深化对复杂动态耦合问题的理解。

34,875

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧