草庐IT

php - SP 插入后,下一页结果为空,直到重新加载

coder 2023-06-11 原文

我有一个将数据插入数据库的存储过程(从现在开始为 SP)(SaveClient,见下文)。当 SP 完成后,我将 PHP 页面重定向到另一个列出条目的 PHP 页面(FetchObjectList,见下文)。在我重新加载/刷新页面之前,列表不会返回新创建的记录。

存储过程末尾有一个COMMIT,我在调用SP后关闭PHP代码中的数据库连接,检查错误但没有出错。

页面本身返回一个 200 状态码,这意味着它没有被缓存,因此也不能与浏览器相关。

当前的解决方法是在 PHP 代码中使用 sleep(1),但是当代码上线时,我不知道它是否足够。我当然宁愿让 MySQL 提供正确的结果集。

编辑:我正在使用 PHP 的 MySQLi 对象接口(interface),了解一下可能会有用。 ;)

我的开发计算机安装了 PHP 5.2.17、MySQL 5.0.51a (InnoDB) 和 Apache 2.2.17,并在 Windows 7 x64 上运行。

更新

在 SaveClient 的末尾添加了以下行 CALL FetchObjectList('client_tbl', NULL, NULL, 1, 'client_tbl.name ASC', NULL, NULL);。结果集中在呈现的结果集中没有新创建的客户端。

更新 2

我尝试使用 SQL_NO_CACHE,如 here 所示但无济于事。

我现在将直接在 PHP 中尝试相同的 SQL,而不是调用 SP。

9 月 3 日至 20 日更新

到目前为止,我已经尝试了任何合理的答案/评论,但没有任何运气。我今天尝试更新我的 PHP 和 MySQL 版本(因为我今天了解到实时服务器将在 PHP 5.3.something 和 MySQL 5.1.something 上运行)但没有让它工作。我需要更新 PHP 以获得更新的 php_mysqli.dll/libmysql.dll 因为我得到的只支持高达 5.0.51a 并且可能有我的问题,因为实际数据库中没有任何工作。我尝试了 MySQL 安装中的 libmysql.dll 无济于事。

请注意,我还更改了包含的 PHP 代码,因为我实际上复制了错误的调用 user_tbl 而不是 client_tbl 的代码,并且还对其进行了简化(删除了多查询)但结果仍然相同。

我不知道赏金会发生什么,如果它恢复给我,我会再次添加它。

存储过程SaveClient

DELIMITER //

DROP PROCEDURE IF EXISTS work.SaveClient//

CREATE PROCEDURE work.SaveClient(
        IN ObjectID INT,
        IN UserID INT,
        IN ClientName VARCHAR(60),
        IN VersionFrom DATETIME,
        IN VersionTo DATETIME)
root:BEGIN

DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;

/* 
    Default values ---------------------------------------------------------------------------------------------------------
*/
    # Used to block INSERT/UPDATEs
    SET @DoChanges      = TRUE;

    SET @Fields     = '*';
    SET @Version        = NULL;
    SET @UserVersion    = NULL;
    SET @DateNow        = NOW();
    SET @VersionActive  = CONCAT(
        '( ( NOW() BETWEEN ', 
        'version_from AND ', 
        'version_to ) OR ( ', 
        'version_from < NOW() AND ', 
        'version_to IS NULL ) )'
    );

    IF VersionFrom IS NULL THEN
        SET VersionFrom = @DateNow;
    END IF;

/*
    Search for client ------------------------------------------------------------------------------------------------------
*/
    IF ObjectID IS NOT NULL THEN
        SET @Client = CONCAT(
            'SELECT version INTO @Version FROM client_tbl WHERE object_id = ',
            ObjectID,
            ' AND ',
            @VersionActive
        );
        PREPARE stmt FROM @Client;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;

        # Check if there are any changes
        IF @Version IS NOT NULL THEN
            SELECT name INTO @Name FROM client_tbl WHERE name = ClientName AND version = @Version;
            IF @Name = ClientName THEN 
                SET @errorMsg = "Duplicate entry";
                SET @errorCode = "S0000002";
                SELECT @errorCode, @errorMsg;
                LEAVE root;
            END IF;
        END IF;

    END IF;
/*
    Search for user ---------------------------------------------------------------------------------------------------------
*/
    # Create this as a function
    IF UserID IS NOT NULL THEN
        SET @User = CONCAT(
            'SELECT version INTO @UserVersion FROM user_tbl WHERE object_id = ',
            UserID,
            ' AND ',
            @VersionActive
        );
        PREPARE stmt FROM @User;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END IF;

    IF @UserVersion IS NULL THEN
        SET @errorMsg = "User is missing";
        SET @errorCode = "U0000099";
        SELECT @errorCode, @errorMsg;
        LEAVE root;
    END IF;

/*
    Add the client ---------------------------------------------------------------------------------------------------------
*/
    # Close the current version
    IF @Version IS NOT NULL THEN 
        IF @DoChanges = TRUE THEN 
            CALL UpdateVersion(
                ObjectID, 
                UserID, 
                @Version, 
                @DateNow, 
                'client_tbl'
            );
            SET @Version = @Version + 1;
        END IF;
    ELSE
        SET @Version = 1;
    END IF;

    IF @DoChanges = TRUE THEN 

        IF ObjectID IS NULL THEN
            INSERT INTO 
                object_tbl 
                (
                    object_class_id, 
                    created,
                    created_by
                )
                VALUES(
                    2,
                    NOW(),
                    UserID
                )
            ;
            SET ObjectID = LAST_INSERT_ID();
        END IF;

        INSERT INTO 
            client_tbl 
            (
                object_id, 
                version, 
                version_from, 
                version_to, 
                changed, 
                changed_by, 
                name
            ) 
            VALUES(
                ObjectID,
                @Version,
                VersionFrom,
                NULL,
                @DateNow,
                UserID,
                ClientName
            )
        ;
    END IF;

    COMMIT;
END //

DELIMITER ;

存储过程 FetchObjectList

DELIMITER //

DROP PROCEDURE IF EXISTS work.FetchObjectList//

CREATE PROCEDURE work.FetchObjectList(
        IN ObjectType VARCHAR(60),
        IN ObjectSubType VARCHAR(60),
        IN ObjectSubID INT,
        IN IsActive INT,
        IN OrderBy VARCHAR(100),
        IN SetStart INT,
        IN MaxResults INT)
root:BEGIN

DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;

    # Allow the "JSON" output be a max of 8kb
    SET GLOBAL group_concat_max_len = 8096;

/* 
    Default values ---------------------------------------------------------------------------------------------------------
*/
    SET @Fields     = '*';
    SET @VersionWhere   = '1'; # Get everything
    SET @Special        = '';
    SET @OrderBy        = '';
    SET @SetStart       = '';
    SET @MaxResults     = '';
    SET @JoinIn     = '';

    IF IsActive = 1 THEN
        SET @VersionWhere = CONCAT(
            '( NOW() BETWEEN ', 
            ObjectType, 
            '.version_from AND ', 
            ObjectType, 
            '.version_to OR ( ', 
            ObjectType, 
            '.version_from < NOW() AND ', 
            ObjectType, 
            '.version_to IS NULL ) )'
        );
    END IF;

    IF OrderBy != '' THEN
        SET @OrderBy = CONCAT(
                'ORDER BY ', 
                OrderBy
        );
    END IF;

/*
    Specials for each type -------------------------------------------------------------------------------------------------
*/

/*
    - Clients ------------
*/

    IF ObjectType = 'client_tbl' THEN
        SET @Fields = '
            *, 
            client_tbl.object_id AS object_id, 
            (
                SELECT 
                    COUNT(*) AS Total 
                FROM 
                    client_user_privilege_tbl cup 
                WHERE 
                    cup.client_id = client_tbl.object_id 

            ) AS usercount
        ';
    END IF;
/*
    - Configuration ------------
*/

    IF ObjectType = 'configuration_tbl' THEN
        SET @Fields = '
            *
        ';
    END IF;
/*
    Add upp the query to run -----------------------------------------------------------------------------------------------
*/
    SET @Query = CONCAT(
        'SELECT ',
        @Fields,
        ' FROM ', 
        ObjectType, 
        ' ',
        @JoinIn, 
        ' WHERE ', 
        @VersionWhere,
        ' ',
        @Special, 
        @OrderBy

    );

    PREPARE stmt FROM @Query;

    EXECUTE stmt;

    DEALLOCATE PREPARE stmt;

    COMMIT;

END //

DELIMITER ;

PHP 代码片段(9 月 20 日更新)

$query = "CALL FetchObjectList('client_tbl', NULL, NULL,  1, NULL, NULL, NULL)";
addTrace($query);

$rs = $db->query($query);
if( $rs ) {
    addTrace('Query done -> Results: ' . $rs->num_rows);
    while($r = $rs->fetch_assoc()){
        $fetchArray[] = $r;
    }
    $count = $rs->num_rows;
    $rs->close();
    $db->next_result();
} else {
    addTrace('Query failed -> ' . $db->error);
    flushTrace();
    exit;
}

最佳答案

由于它是 mysql 的一个相当陈旧的版本,因此这与错误相关并不会让我感到惊讶,但我会 - 在你的位置 - 想知道的一件事是这是否可以通过 not 使用交易。 (例如 autocommit = on)。

对于该版本 5.0,我还将检查查询缓存并将其全部禁用而不是每个查询(请参阅 SHOW VARIABLES LIKE 'have_query_cache'; SET GLOBAL query_cache_size =0; )。这至少会消除那些在这个问题中发挥作用的人,重现(或尝试)问题,看看是否有任何改变。如果没有,我会开始搜索特定的错误,特别是当查询缓存被禁用并且它仍然在不使用事务的情况下执行此操作时。

我验证了对 5.0 mysql (innodb) 的支持。

  • innodb_flush_log_at_trx_commit = 1
  • innodb_flush_method = O_DIRECT

在您的 my.cnf 中专门设置这些选项,最重要的一项。他们很好地解释了那些做什么。

http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

关于php - SP 插入后,下一页结果为空,直到重新加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12131011/

有关php - SP 插入后,下一页结果为空,直到重新加载的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  5. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  6. ETH 徘徊在 1,700 美元附近;下一步是什么? - 2

    以太坊价格分析表明横盘整理,偏向中性。价格从前一交易日的高点1,791美元回落后正在盘整。但是,有趣的是,多头在1,680美元附近持有重要支撑。多头在1,700美元的心理水平附近聚集动能,并准备在接下来的几个交易日推向1,800美元。以太坊价格显示出盘整迹象,因为它形成了多个连续的顶部形态。这种回撤可能是第二大加密货币下一轮上涨的基石。以太坊连续第二个交易日走低。过去10天,价格在1,590-1,760美元的短期区间内盘整。每日烛台高于1,800美元将维持ETH的进一步上涨。ETH价格走低日线图上,以太坊价格在上升趋势线附近获得一轮支撑。来自879.80美元低点的看涨趋势线为ETH买家提供了支

  7. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  8. ruby - 如何在 Ruby 字符串中插入项目符号字符? - 2

    我正在尝试创建一个带有项目符号字符的Ruby1.9.3字符串。str="•"+"helloworld"但是,当我输入它时,我收到有关非ASCII字符的语法错误。我该怎么做? 最佳答案 你可以把Unicode字符放在那里。str="\u2022"+"helloworld" 关于ruby-如何在Ruby字符串中插入项目符号字符?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1195

  9. ruby-on-rails - CarrierWave - PDF - 只选择第一页 - 2

    我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful

  10. ruby - 在 ruby​​ 中使用自动创建插入数组 - 2

    我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?

随机推荐