php - 处理并发问题的最佳方法

标签 php mysql postgresql concurrency

我有一个 LAPP(linux、apache、postgresql 和 php)环境,但问题在 Postgres 或 Mysql 上都非常相同。

我开发了一个 cms 应用程序,用于处理客户、文档(估算、发票等)和其他数据,在 1 个 postgres 数据库中构建,具有许多模式(每个使用该应用程序的客户都有一个);让我们假设大约有 200 个模式,每个模式由 15 人(平均)同时使用。

编辑 :我确实在每个表上都有一个名为 last_update 的时间戳字段,以及一个每次更新行时都会更新时间戳的触发器。

情况是:

  • People Foo 和 Bar 正在编辑文档 0001,使用包含每个文档详细信息的表单。
  • 例如,Foo 更 retrofit 运详细信息。
  • 酒吧更改电话号码,以及文件中的一些项目。
  • Foo 按“保存”按钮,应用程序更新数据库。
  • 栏后按“保存”按钮,重新发送带有旧货件详细信息的表格。
  • 在数据库中,Foo 更改已丢失。

  • 我想要的情况:
  • Foo、Bar、John、Mary、Paoul 正在编辑文档 0001,使用包含每个文档详细信息的表单。
  • 例如,Foo 更 retrofit 运详细信息。
  • 巴和其他人改变了一些东西。
  • Foo 按“保存”按钮,应用程序更新数据库。
  • Bar 和其他人收到警报“警告!此文档已被其他人更改。单击此处加载实际数据'。

  • 我想知道使用 ajax 来做到这一点;只需使用带有文档 id 和上次更新时间戳的隐藏字段,每 5 秒检查上次更新时间是否相同并且什么都不做,否则,显示警告对话框。

    因此,页面 check-last-update.php 应该类似于:
    <?php
    //[connect to db, postgres or mysql]
    $documentId = isset($_POST['document-id']) ? $_POST['document-id'] : 0;
    $lastUpdateTime = isset($_POST['last-update-time']) ? $_POST['last-update-time'] : 0;
    //in the real life i sanitize the data and use prepared statements;
    $qr = pg_query("
        SELECT
            last_update_time
        FROM
            documents
        WHERE
            id = '$documentId'
    ");
    $ray = pg_fetch_assoc($qr);
    if($ray['last_update_time'] > $lastUpdateTime){
        //someone else updated the document since i opened it!
        echo 'reload';
    }else{
        echo 'ok';
    }
    ?>
    

    但我不喜欢每 5 秒为每个打开一个(或多个...)文档的用户强调 db。

    那么,在不破坏数据库的情况下,还有什么有效的解决方案?

    我想使用文件,例如为每个文档创建一个空的 txt 文件,每次更新文档时,我都会“触摸”更新“上次修改时间”的文件......但我想这会更慢比 db 并在我有很多用户编辑同一文档时出现问题。

    如果其他人有更好的想法或任何建议,请详细描述!

    * - - - - - 更新 - - - - *

    我绝对选择不点击数据库来检查“上次更新时间戳”,不要介意查询是否很快,(主)数据库服务器还有其他任务需要完成,不喜欢增加他对那件事的过载的想法.

    所以,我采取这种方式:
  • 每次有人更新文档时,我都必须做一些事情来在数据库环境之外签署新的时间戳,例如不问数据库。我的想法是:
  • 文件系统:对于每个文档,我创建一个名为文档 ID 的空 txt 文件,每次文档更新时,我都会“触摸”该文件。我希望有成千上万的空文件。
  • APC,php 缓存:这可能比第一种更灵活,但我想知道将成千上万的数据永久保存在 apc 中是否不会减慢 php 执行本身,或消耗服务器内存。我有点害怕选择这种方式。
  • 另一个 db、sqlite 或 mysql(使用简单的 db 结构更快更轻)用于仅存储文档 ID 和时间戳。
  • 无论我选择哪种方式(文件、apc、sub-db),我都在认真考虑在子域上使用另一个网络服务器(lighttp?),来处理所有这些......长轮询请求。

  • 另一个编辑:

    该文件的方式不起作用。

    APC 可以成为解决方案。

    命中数据库也可以是解决方案,创建一个表来处理时间戳(只有两列,document_id 和 last_update_timestamp),需要尽可能快和轻。

    长轮询:我会选择这种方式,在apache下使用lighttpd来加载静态文件(图片、css、js等),并且只针对这种类型的长轮询;这将减轻 apache2 的负载,特别是对于轮询。

    Apache 会将所有这些请求代理到 lighttpd。

    现在,我只需要在 db 解决方案和 APC 解决方案之间做出决定..

    ps:感谢所有已经回答我的人,你真的很有用!

    最佳答案

    我同意我可能不会为此访问数据库。我想我会使用 APC 缓存(或其他一些内存缓存)来维护这些信息。您所描述的显然是详细记录级别的乐观锁定。数据库结构中的级别越高,您需要处理的就越少。听起来您想检查结构中的多个表。

    我会维护一个缓存(在 APC 中)的 ID 和由表名键控的上次更新时间的时间戳。例如,我可能有一个表名数组,其中每个条目都以 ID 为键,实际值是最后更新的时间戳。可能有很多方法可以用数组或其他结构来设置它,但你明白了。我可能会向缓存添加超时,以便在一段时间后删除缓存中的条目 - 即,我不希望缓存增长并假设 1 天前的条目不再有用)。

    使用此架构,您需要执行以下操作(除了设置 APC):

  • 在对任何(适用)表进行任何更新时,使用新时间戳更新 APC 缓存条目。
  • 在 ajax 中,只要“返回”到 php(获取 APC 缓存以检查条目),而不是“返回”到数据库的所有方式。
  • 关于php - 处理并发问题的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1779317/

    相关文章:

    php - PHP:如何下载YouTube视频?

    PHP获取前一个数组元素知道当前数组键

    php - 开始使用 PDO,第一个程序无法运行

    php - 我如何更改此查询以适合 Laravel 的查询生成器?

    mysql - 通过 ssh 进行工作台迁移 - 如何设置隧道

    php - 检查登录用户是否有权访问内容的 MySQL 查询? (其中内容属于用户注册的类(class))

    php - 如何从php代码中获取Mysql执行消息发送器?

    sql - 显示两个范围之间的所有数据点

    postgresql - 从 Postgres 数据库中删除所有函数

    java - Hibernate 在 PostgreSQL 中使用驼峰格式的主键