我在Mysql中使用一个存储过程创建了3个临时表,用于存储数据库表中的记录,然后用于从存储记录的子集中选择最终结果。
问题在于,虽然假设存储过程中的临时表对于每个MySQL会话都是唯一的,但我从存储过程的不同调用中获得了混合结果。
让我们用一个真实案例解释问题:
我们用户A,B,C 访问我的网站,在“同一时刻”进行不同的搜索。
用户A搜索“AAAA”,用户B搜索“BBBB”,用户C搜索“CCCC”,然后网络服务器“同时”向数据库服务器进行3次调用
对存储过程的调用是:
call SP('AAAA');
call SP('BBBB');
call SP('CCCC');
每次调用的结果应该是类似于: 对于呼叫SP('AAAA');
Record_AAAA1
Record_AAAA2
Record_AAAA3
对于呼叫SP('BBBB');
Record_BBBB1
Record_BBBB2
Record_BBBB3
Record_BBBB4
致电SP('CCCC');
Record_CCCC1
Record_CCCC2
但我得到的结果类似于: 对于呼叫SP('AAAA');
Record_AAAA1
Record_AAAA2
Record_BBBB2
Record_AAAA3
Record_BBBB4
Record_CCCC2
对于呼叫SP('BBBB');
Record_BBBB1
Record_BBBB2
Record_CCCC1
Record_CCCC2
Record_AAAA1
Record_AAAA2
Record_BBBB3
Record_BBBB4
致电SP('CCCC');
Record_CCCC1
Record_AAAA1
Record_AAAA2
Record_CCCC2
有时我没有得到任何结果,有时我得到正确的结果,所以结果取决于执行。
如果超过1个用户同时使用网络搜索,我的结果会出错。正如我所读到的,临时表对于每个不同的会话都是唯一的,因此存储过程的每个不同执行都应该使用不同的临时表。
这是 MySQL服务器问题,因为我已经通过Linux控制台通过MySQL客户端连接到同一服务器的2台计算机进行了一些测试。
这在生产数据库服务器和我的本地数据库服务器中发生。
我正在使用 MySQL服务器版本:5.1.67 -0ubuntu0.11.10.1-log(Ubuntu)
为什么会发生这种情况?怎么能解决呢?
提前感谢,如果您需要来自数据库服务器的一些配置数据,请告诉我。
存储过程非常复杂和混乱(http://pastebin.com/pQ6VqHBn),因此简而言之它的作用如下:
1)从调用接收参数
2)根据参数
创建对tmpfinal临时表的插入查询3)使用where搜索词
从tmpfinal中选择插入到tmpdest临时表中4)从tmpfinal中删除插入tmp dest
的记录5)使用where搜索词从tmpfinal中选择插入tmpnorm临时表
6)通过search_term_punctuation
从tmpnorm临时表顺序中选择*7)通过search_term_punctuation2
从tmpdest临时表顺序中选择*插入到tmpnorm和tmpdest中的结果有时是来自不同并发存储过程调用的混合结果。
存储过程中的表格定义
DROP TEMPORARY TABLE IF EXISTS tmpfinal;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpfinal (
convo int,
justo int,
rankin int,
even int,
centro int,
destacado int,
nivel decimal(12,8),
num_fila int AUTO_INCREMENT PRIMARY KEY,
num_fila_centro int
);
DROP TEMPORARY TABLE IF EXISTS tmpdest;
CREATE TEMPORARY TABLE IF NOT EXISTS tmpdest (
id int AUTO_INCREMENT PRIMARY KEY,
convo int,
tipo_destacado enum ('superdestacado', 'destacado', 'anadido')
);
DROP TABLE IF EXISTS tmpnorm;
CREATE TABLE IF NOT EXISTS tmpnorm (
id int AUTO_INCREMENT PRIMARY KEY,
convo int
);
生成插入到TMPFINAL QUERY的示例
insert into tmpfinal
(convo,justo,rankin,even,nivel,destacado,centro)
select distinct convocatoria_id,justo,ranking,evento_id,niveldes,destacado,centro_id from
(select distinct MATCH (eventos_busqueda.temario_ind) AGAINST ('+salud') as ranking,
MATCH (eventos_busqueda.curso_ind) AGAINST ('+salud' IN BOOLEAN MODE) as justo, eventos.evento_id, centros.centro_id,
orden_bus +
(CASE
WHEN convocatoria_opciones_webs.espacio_id=2 THEN 1
WHEN convocatoria_opciones_webs.espacio_id=6 THEN 2
WHEN convocatoria_opciones_webs.espacio_id=1 THEN 3
else 4 END ) * 1000 +
CAST( 1/( (
case
when convocatoria_opciones_webs.nivel IS NULL then 1
when convocatoria_opciones_webs.nivel=0 then 1
else convocatoria_opciones_webs.nivel
end)
* (
case
when preciocupon IS NULL then 1
when preciocupon=0 then 1
else preciocupon
end)) as decimal(14,10)) as niveldes ,
convocatorias.convocatoria_id ,
CASE
WHEN convocatoria_opciones_webs.orden_bus < 100 THEN 1
ELSE 0
END AS destacado
FROM eventos
INNER JOIN convocatorias ON eventos.evento_id = convocatorias.evento_id
INNER JOIN convocatoria_opciones_webs ON convocatoria_opciones_webs.convocatoria_id = convocatorias.convocatoria_id
LEFT JOIN aux_provincias ON convocatorias.provincia_id = aux_provincias.Provincia_id
INNER JOIN centros ON convocatorias.centro_id = centros.centro_id
INNER JOIN eventos_modalidad ON eventos_modalidad.Modalidad_id = eventos.Modalidad_id
INNER JOIN eventos_imparticion ON eventos_imparticion.Imparticion_id = eventos.Imparticion_id
INNER JOIN webs ON convocatoria_opciones_webs.web_id = webs.web_id and webs.web_id = 1
INNER JOIN evento_subtemas on eventos.evento_id=evento_subtemas.evento_id
INNER JOIN evento_temas on eventos.evento_id=evento_temas.evento_id
INNER JOIN subtemas on subtemas.subtema_id=evento_subtemas.subtema_id
INNER JOIN temas on temas.tema_id = evento_temas.tema_id
inner join eventos_busqueda on eventos.evento_id=eventos_busqueda.evento_id
WHERE (convocatorias.publicar = 1 OR convocatorias.publicar = 3) AND (convocatorias.inicio > CURRENT_DATE() OR convocatorias.inicio IS NULL)
and match (eventos_busqueda.curso_ind, eventos_busqueda.temario_ind) AGAINST ('+salud' IN BOOLEAN MODE)
AND not (convocatoria_opciones_webs.espacio_id is null) and not convocatoria_opciones_webs.nivel is null
and webs.web_id=1) as t
生成插入TMPDEST QUERY的示例
INSERT INTO tmpdest (convo, tipo_destacado)
SELECT Z.convo, tipo_destacado FROM (
SELECT convo, tipo_destacado FROM (
SELECT (@lim-@r) as orden_fila,tmpfinal.centro, tmpfinal.nivel,tmpfinal.convo,
@cg <> tmpfinal.centro AS centro_distinto,
CASE
WHEN cow.orden <= 3 THEN 'superdestacado'
WHEN tmpfinal.destacado = 1 THEN 'destacado'
ELSE NULL
END AS tipo_destacado,
CASE
WHEN @cg <>tmpfinal.centro THEN @r := @lim
ELSE 1
END > 0 AND (@r := @r - 1) >= 0 AND (@cg := tmpfinal.centro) IS NOT NULL
FROM tmpfinal
INNER JOIN convocatoria_opciones_webs AS cow ON tmpfinal.convo = cow.convocatoria_id
WHERE destacado=1 AND cow.web_id = 1 AND justo >= 1
ORDER BY tmpfinal.justo DESC, tmpfinal.rankin DESC, tmpfinal.nivel ASC ) T
WHERE centro_distinto = 1 OR (orden_fila < 5 AND centro_distinto = 0)
LIMIT 15 ) Z
插入TMPNORM QUERY的示例
INSERT INTO tmpnorm (convo, tipo_destacado)
SELECT Z.convo, tipo_destacado FROM (
SELECT convo, tipo_destacado FROM (
SELECT (@lim-@r) as orden_fila,tmpfinal.centro, tmpfinal.nivel,tmpfinal.convo,
@cg <> tmpfinal.centro AS centro_distinto,
CASE
WHEN cow.orden <= 3 THEN 'superdestacado'
WHEN tmpfinal.destacado = 1 THEN 'destacado'
ELSE NULL
END AS tipo_destacado,
CASE
WHEN @cg <>tmpfinal.centro THEN @r := @lim
ELSE 1
END > 0 AND (@r := @r - 1) >= 0 AND (@cg := tmpfinal.centro) IS NOT NULL
FROM tmpfinal
INNER JOIN convocatoria_opciones_webs AS cow ON tmpfinal.convo = cow.convocatoria_id
WHERE destacado=1 AND cow.web_id = 1 AND justo >= 1
ORDER BY tmpfinal.justo DESC, tmpfinal.rankin DESC, tmpfinal.nivel ASC ) T
WHERE centro_distinto = 1 OR (orden_fila < 5 AND centro_distinto = 0)
LIMIT 15 ) Z
从TMPNORM / TMPDEST QUERY生成选择的示例
select distinct tmpnorm.id, IFNULL(IF(centros.acronimos<>'', centros.acronimos, centros.centro), centros.centro) as centro, centros.centro_id,
eventos_modalidad.color AS color, eventos_modalidad.tipo AS tipo,convocatorias.evento_id,
eventos_imparticion.tipo AS tipoevento,
convocatorias.convocatoria_id, eventos.evento, convocatorias.inicio,
aux_provincias.provincia,SUBSTRING(temario, LOCATE(SUBSTRING_INDEX(temario, 'salud', 1), temario), 300) AS temario,
orden_home as orden,convocatorias.horasduracion, convocatorias.textoduracion AS textoduracion, convocatorias.preciocurso,
convocatorias.gratuito,case when tipofecha IS NULL then '' else COALESCE(tipofecha , '') +' '+ COALESCE(anotipofecha , '') end as tipofecha,
convocatorias.preoferta, convocatorias.finoferta,convocatorias.subvencionado, convocatorias.pais_id, centros.pais_id AS pais_cen
FROM eventos
INNER JOIN convocatorias ON eventos.evento_id = convocatorias.evento_id
INNER JOIN convocatoria_opciones_webs ON convocatoria_opciones_webs.convocatoria_id = convocatorias.convocatoria_id
LEFT JOIN aux_provincias ON convocatorias.provincia_id = aux_provincias.Provincia_id
INNER JOIN centros ON convocatorias.centro_id = centros.centro_id
INNER JOIN eventos_modalidad ON eventos_modalidad.Modalidad_id = eventos.Modalidad_id
INNER JOIN eventos_imparticion ON eventos_imparticion.Imparticion_id = eventos.Imparticion_id
INNER JOIN webs ON convocatoria_opciones_webs.web_id = webs.web_id and webs.web_id = 1
INNER JOIN evento_subtemas on eventos.evento_id=evento_subtemas.evento_id
INNER JOIN evento_temas on eventos.evento_id=evento_temas.evento_id
INNER JOIN tmpnorm ON tmpnorm.convo=convocatorias.convocatoria_id
INNER JOIN subtemas on subtemas.subtema_id=evento_subtemas.subtema_id
INNER JOIN temas on temas.tema_id = evento_temas.tema_id
order by tmpnorm.id
答案 0 :(得分:1)
tmpnorm
不是临时表,因此它将在您的所有会话中共享。
CREATE TABLE IF NOT EXISTS tmpnorm (
id int AUTO_INCREMENT PRIMARY KEY,
convo int
);
每个会话可能在临时表tmpfinal
和tmpdest
中有自己的孤立数据,但只要它们插入tmpnorm
,它们就会合并,使用来自所有数据的所有数据会话。然后,此数据将用于最终查询,该查询将连接到所有其他非临时表。