2

データベースのテーブルからレコードを格納する 3 つの一時テーブルを作成し、格納されたレコードのサブセットから最終結果を選択するために使用するストアド プロシージャを Mysql で使用しています。

問題は、ストアド プロシージャ内の一時テーブルは MySQL セッションごとに一意であると想定されていますが、ストアド プロシージャからのさまざまな呼び出しからさまざまな結果が得られることです。

実際のケースのシナリオで問題を説明しましょう。

私のウェブサイトにアクセスするユーザーA、B、Cが「同時に」さまざまな検索を行っています。

ユーザー A が「AAAA」を検索し、ユーザー B が「BBBB」を検索し、ユーザー C が「CCCC」を検索すると、Web サーバーは「同時に」データベース サーバーに対して 3 つの呼び出しを行います

ストアド プロシージャの呼び出しは次のとおりです。

call SP('AAAA'); 
call SP('BBBB'); 
call SP('CCCC');

各呼び出しの結果は次のようになります。 For call SP('AAAA');

Record_AAAA1
Record_AAAA2
Record_AAAA3

呼び出し用 SP('BBBB');

Record_BBBB1
Record_BBBB2
Record_BBBB3
Record_BBBB4

呼び出し用 SP('CCCC');

Record_CCCC1
Record_CCCC2

しかし、得られる結果は次のようなものです。 For call 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

結果が得られない場合もあれば、正しい結果が得られる場合もあるため、結果は実行に依存します。

そのため、複数のユーザーが同時に Web 検索を使用すると、間違った結果が得られます。私が読んだように、一時テーブルは異なるセッションごとに一意であるため、ストアドプロシージャの実行ごとに異なる一時テーブルを使用する必要があります。

Linuxコンソールを介してMySQLクライアントを介して同じサーバーに接続された2台のコンピューターでいくつかのテストを行ったため、これはMySQLサーバーの問題です。

これは、運用データベース サーバーとローカル データベース サーバーで発生します。

MySQL サーバーのバージョンを使用しています: 5.1.67 -0ubuntu0.11.10.1-log (Ubuntu)

なぜこれが起こっているのでしょうか?どうすれば解決できますか?

事前に感謝します。データベース サーバーからの構成データが必要な場合はお知らせください。


ストアド プロシージャは非常に複雑で面倒なので ( http://pastebin.com/pQ6VqHBn )、簡単に言うと次のようになります。

1) 呼び出しからパラメーターを受け取る

2) パラメーターに応じて、tmpfinal 一時テーブルへの挿入クエリを作成します。

3) where 検索語を使用して、tmpfinal からの選択から tmpdest 一時テーブルに挿入します。

4) tmp dest に挿入されたレコードを tmpfinal から削除します。

5) where 検索語を使用して、tmpfinal からの選択から tmpnorm 一時テーブルに挿入します。

6) select * from tmpnorm temp table order by search_term_punctuation

7) select * from tmpdest temp table order by search_term_punctuation2

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 
);

生成された INSERT INTO TMPFINAL クエリの例

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 クエリへの挿入の例

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

INSERT INTO TMPNORM クエリの例

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 の例

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
4

1 に答える 1

1

tmpnormは一時テーブルではないため、すべてのセッションで共有されます。

CREATE TABLE  IF NOT EXISTS tmpnorm (
    id int AUTO_INCREMENT PRIMARY KEY,
    convo int 
);

tmpfinal各セッションは、一時テーブルおよびに独自の分離されたデータを持つ場合がありますが、それらがtmpdestに挿入されるとすぐに、tmpnormすべてのセッションからのすべてのデータを使用してマージされます。次に、このデータは、他のすべての非一時テーブルに結合する最終クエリで使用されます。

于 2013-02-08T15:59:31.403 に答える