0

我手上有一个非常可怕的问题,由于某种原因,数据正在从特定表的列中擦除,我不知道为什么。

该表称为events。表格内有许多列、名称、日期等,但最近我在名为“schedule”的字段中放置了一个 TEXT 类型的字段。

在网页上,您可以在不同的选项卡中编辑事件并创建时间表(使用 jQuery 克隆 / 等的字段),然后当时间表数据保存到数据库中时,HTML $_POST 数据使用以下方法转换为 JSON 数组json_encode

$db->prepared['schedule'] = json_encode(
    array(
        "scheduleday" => ($_POST['scheduleday'] ?? array()), 
        "scheduletime" => ($_POST['scheduletime'] ?? array()), 
        "scheduledescription" => ($_POST['scheduledescription'] ?? array()), 
        "schedulevenue" => ($_POST['schedulevenue'] ?? "")
    )
);

生成的 json 数组可能如下所示,例如:

{"scheduleday":{"1":"2020-08-25","2":"2020-08-26"},"scheduletime":{"1":["19:30","20:00 - 20:50"],"2":["14:00 - 14:50","14:50 - 15:00","15:00 - 15:50","15:50 - 16:00","16:00 - 16:50"]},"scheduledescription":{"1":["Introduction","John Smith"],"2":["John Smith","Break","John Smith teaching","Break","John Smith teaching"]},"schedulevenue":"1 Acia Avenue"}

在这被插入或更新到 mysql 数据库之后,它被发送到一个函数,该函数使用 fpdf 将 json 数组转换为可以下载的 PDF。

这很好用,除了一个问题。随机(或看似随机的)时间表正在丢失。我们可以在一天后创建一个计划,然后在一周后,或者在几天后,突然文件将被删除并且表中的列被删除。表中没有其他数据被删除,除了计划之外什么都没有。

这是我试图找出发生的事情:

SQL 触发器

我在事件表上设置了一个触发器,它将数据转储到一个名为event_triggerAFTER 运行更新的表中。这是触发器的代码:

BEGIN
INSERT INTO `event_trigger` (oldID,name,old_schedule,new_schedule) VALUES
(OLD.id,
 OLD.name,
 OLD.schedule,
 NEW.schedule);
END

从某种意义上说,这很有帮助,因为我现在知道是否存在缺少时间表的事件,因为 NEW.schedule 将为空。然而,最近两次日程安排已经丢失(实际上是昨天和今天),它是在办公时间之外,18:45 和 19:22,所以没有人应该对那些时间的事件进行任何更新。

.txt 文件日志

我所做的另一件事是在更新事件的页面上我放置了一个文本日志,它将准备好的变量、SQL 语句以及用户和用户 ID 转储到一个文本文件中。不幸的是,这不起作用,因为当一个时间表丢失时,它不会在那里登录。告诉我的只是它发生在其他地方。

我不知道如何进一步缩小范围。删除事件时没有用户活动。我得到的最接近的是使用触发器。但是我很有限,因为来自触发器的信息还不够;我无法获得 IP、SQL 语句、用户 ID 或类似的东西。只是 OLD 和 NEW 变量。

谁能帮我想想办法调查,我将不胜感激。这已经持续了一个多月了,这令人愤怒,因为我只是不明白为什么会这样。

我能想到的唯一额外选项是打开完整的 SQL 日志,但我不愿意这样做,因为它会大大降低服务器速度。

4

1 回答 1

1

你检查过你的网络服务器的日志吗?如果此数据损坏通过您的 Web 应用程序进入,您应该能够看到不幸事件的确切时间和原始 IP 地址。您可能还能够找出您的 Web 应用程序的哪个页面导致了问题。

为了更准确地跟踪数据库服务器中的内容,请将以下列添加到您的event_trigger表中:

  • 时间戳(触发器触发时)
  • 用户(发出触发触发器的 UPDATE 的 MySQL 主机和用户)
  • 查询(UPDATE 查询的文本)

然后改变你的触发器说

BEGIN
  INSERT INTO event_trigger 
        (oldID,name,old_schedule,new_schedule, ts, user, query)
  VALUES
  (OLD.id,
   OLD.name,
   OLD.schedule,
   NEW.schedule,
   NOW(),
   CURRENT_USER(),
   (SELECT INFO FROM information_schema.process_list WHERE id=CONNECTION_ID())
);
END

然后,您的 event_trigger 表将显示用户webapp@localhostcybercreep@cracker.example.com发布 UPDATE 的用户、发布时间以及确切的查询是什么。

(通过确切的查询,您可以搜索您的代码库以尝试追踪正在运行的函数。)

一旦您知道哪个数据库用户正在发出查询,您可以考虑在工作时间之后暂停该特定用户的访问,并查看谁在抱怨。但请记住,数据库用户可能是您的 Web 应用程序使用的通用用户名,因此它可能不会告诉您太多信息。

这很可能是合法的网络应用程序用户错误地滥用了您的系统。

专业提示:在所有应用程序表中放置自动时间戳列,以便跟踪更改。添加

 ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

列到您的表中,MySQL 负责更新它们。

专业提示 2(更难)将操作日志表添加到您的数据库中,并让您的 Web 应用程序在每次用户执行操作时向其中插入一行。然后,您可以运行诸如“昨天 19:00 到 19:30 之间谁做了什么?”之类的查询。客户支持人员喜欢能够做到这一点。

于 2020-02-21T13:52:58.273 回答