php - 最佳实践数据库事务和在 PHP 中将文件存储到文件系统

标签 php transactions pdo

如果用户将用户数据与文件一起上传(用户数据存储在数据库中,文件存储在文件系统中),关于完整性的最佳做法是什么?

目前,我会使用 PHP 和 PDO 执行类似于以下代码片段的操作(代码未经过测试,但我希望您能理解我的意思)。我不喜欢 User::insert 方法中的保存图像部分。有解决这个问题的好办法吗?

<?php
User::insert($name, $image, $ext);

Class User{
    static public function insert($name, $image, $ext){
        $conn = DB_config::get();

        $conn->beginTransaction();

        $sth = $conn->prepare("
                                INSERT INTO users (name)
                                values(:name)
                                ;");

        $sth->execute(array(
                                ":name"     =>  $name
                                ));

        if ($conn->lastInsertId() > -1 && Image::saveImage($image, IMAGE_PATH . $conn->lastInsertId(). $ext))
            $conn->commit();
        else
            $conn->rollback();

        return $conn->lastInsertId();
    }
}

Class Image{
    static public function saveimage($image, $filename){
        $ext = self::getExtensionFromFilename($filename);

        switch($ext){
            case "jpg":
            case "jpeg":
                return imagejpeg(imagecreatefromstring($image), $filename);
        }

        return false;
    }
?>

最佳答案

试试这个。

  • 将图像保存到工作区的磁盘中。最好保存到 与最终目标位于同一卷上的工作区。 也最好放在单独的目录下。

  • 开始与数据库的事务。

  • 插入您的用户。

  • 在用户 ID 后重命名图像文件。

  • 提交交易。

它所做的是首先执行风险最高的操作,即保存图像。各种各样的事情都可能在这里发生——系统可能会失败,磁盘可能已满,连接可能会关闭。这(可能)是您操作中最耗时的,因此它绝对是风险最高的。

一旦完成,您就开始交易并插入用户。

如果此时系统出现故障,你的insert会被回滚,image会在临时目录中。但是对于您的真实系统,实际上“什么都没有发生”。可以使用自动功能清理临时目录(即重启时清理,清理超过 X 小时/天的所有内容,等等)。文件在此目录中的时间跨度应该很短。

接下来,将图像重命名为它的最终位置。文件重命名是原子的。它们工作或不工作。

如果系统在此之后,用户行将回滚,但文件将在其最终目的地。但是,如果在重新启动后有人试图添加一个新用户,而这个新用户恰好与失败的用户具有相同的用户 ID,则他们上传的图像将简单地覆盖现有的图像——没有伤害,没有犯规。如果不能重新使用用户标识,您将拥有一个孤立的图像。但这可以合理地每周或每月通过自动化程序清理一次。

最后提交事务。

此时一切都在正确的地方。

关于php - 最佳实践数据库事务和在 PHP 中将文件存储到文件系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11657899/

相关文章:

php - 调用非对象的成员函数 bindValue()。 PHP 版本不同?

php - 如何清理查询以接受表名作为参数 PDO php

php - 将 "popularity"因子与 zend-search lucene 正确集成的最佳方法是什么?

php - 使用 Paypal 交易

java - 即使服务器中途出现故障,如何可靠地确保本地和远程数据副本均已更新

php mysql where 子句

php - 无法使用 JMS 序列化程序将空数组序列化为空 XML 元素

php - 用户上次登录/浏览网站的时间

php - 使用php在单个输入中将多个图像上传到数据库中

.net - SQL Server 和 TransactionScope(带 MSDTC): Sporadically can't get connection