今天碰到一个奇葩的问题,同样的批量插入,一个可以批量插入成功,一个却不能插入成功,请大家看看。以下是伪代码--存储过程A(负责插入SQL)(有参数,这里就不写了,主要用于组装SQL并执行)CREATEPROCEDURE`A`()BEGINREPLACEINTO`table`(`num`)SELECTSUM(`num`)AS`num`FROM`table`;END;--存储过程B(负责循环处理参数,传递给A)CREATEPROCEDURE`B`()BEGINWHILE100DOCALL`A`;ENDWHILE;END;上面的两个存储过程就是我的代码逻辑,每次REPLACEINTO...SELECT...大概需要0.2秒的时间。当我调用CALL`B`的时候,只能第一条插入成功,其他的均无插入,也没有报错。生成的SQL语句是无错误的,因为打印的语句可以手动批量插入。更奇葩的是,,我有一个同样的功能的其他REPLACEINTO...SELECT...(相对执行时间短,0.01秒级),却可以批量插入成功。这个是不是锁导致的呢,我用的InnoDB存储引擎。可能有些情况我说的不太明白:上面的代码是伪代码,循环结构和生成执行SQL均无问题这里主要讨论三个问题:是不是行锁导致的(按说不应该)同样的表,同样的查询结构,为何执行时间短的可以插入(0.001级别),执行时间长的不能插入(0.1级别)执行过程中调用执行过程,是同步执行还是异步执行(即是否等CALL执行完毕后在走流程,还是不等执行完毕,就走下一个循环流程)
2 回答
慕无忌1623718
TA贡献1744条经验 获得超4个赞
我想到了一个原因,正在测试,如果CALL是异步调用,而我SQL执行是这样的:SET@sql=$sql;PREPARESTMTFROM@sql;EXECUTESTMT;DEALLOCATEPREPARESTMT;@sql会相互覆盖。看看测试结论吧。现在代码是这样的:CREATEPROCEDURE`A`()BEGINSET$sql='REPLACEINTO`table`(`num`)SELECTSUM(`num`)AS`num`FROM`table`;';SET@sql=$sql;PREPARESTMTFROM@sql;EXECUTESTMT;DEALLOCATEPREPARESTMT;END;CREATEPROCEDURE`B`()BEGINWHILE100DOCALL`A`;ENDWHILE;END;
泛舟湖上清波郎朗
TA贡献1818条经验 获得超3个赞
你没有说明表的主键和唯一键,猜测id是主键,但replaceinto代入的id始终是0,所以最终数据库里只能有一条记录,如果id是自增长的,试试设成null,或改用insertinto,而不是replaceinto.EDITED我试了下,按你给的存储过程会陷入死循环,因为while100一直为真.可以试试改成这样:delimiter$$CREATEPROCEDURE`A`()BEGINREPLACEINTO`sumtable`(`id`,`mysum`)SELECT0AS`id`,SUM(`mysum`)AS`mysum`FROM`sumtable`;END;$$--存储过程B(负责循环处理参数,传递给A)CREATEPROCEDURE`B`()BEGINDECLAREv1INTDEFAULT100;WHILEv1>0DOCALL`A`;SETv1=v1-1;ENDWHILE;END;$$运行callB()会得到100条记录.
添加回答
举报
0/150
提交
取消