在同一事务中插入和更新同一行? (MySQL)

发布于 2024-10-18 06:21:55 字数 1823 浏览 5 评论 0原文

所以这是我的问题:

我有一个带有可选图像上传字段的文章提交表单。

当用户提交表单时,大致会发生以下情况:

if($this->view->form->isValid($_POST){

$db->beginTransaction();
try{
    // save content of POST to Article table 
    if(!$this->_saveArticle($_POST)){
         return;
        }

    // resize and save image using ID generated by previous condition
    if(!$this->_saveImage($_FILES){            
        $db->rollback();
        return;
        }

    // update record if image successfully generated
    if(!$this->_updateArticle(){
        $db->rollback();
        }
    $db->commit();
    }
}catch (Exception $e){
    $db->rollback()
}

所有模型都使用映射器保存,映射器通过检查代理键是否存在来自动执行“UPSERT”功能

public function save($Model){
   if(!is_null($Model->id_article){
       $Mapper->insert($Model->getFields());
       return;
    }
    $Mapper->update($Model->getFields(),$Model->getIdentity());
}

。文章表具有 ID、标题和 URL 的复合 UNIQUE 索引。此外,我正在生成一个 UID,该 UID 在插入之前添加到模型的 ID 字段(而不是自动递增)

当我尝试执行此操作时,它对于插入表中的第一篇文章运行良好 - 但后续文章调用(具有完全不同的输入)会触发 DUPLICATE KEY 错误。 MySQL 会返回在条件 1 (_saveArticle) 中生成的 ID,并抱怨该键已经存在...

我已经转储了模型字段(以及条件状态 - 即插入 | 更新),并且它们按预期进行(伪):

inserting!
id = null
title = something 
content = something
image = null

updating!
id = 1234123412341234
title = something
content = something else
image = 1234123412341234.jpg

该行数据不存在于数据库中。

我认为这可能是以下几件事之一:

1:我在用户登录时加载辅助数据库适配器,允许他们通过一次登录与多个站点进行交互 - 这可能会以某种方式混淆事务

2: 这是 Zend 事务实现中的一些描述错误(可能由 1 触发)

3: 我需要用 INSERT ... ON 替换 save()重复

4: 我应该重新构建提交过程,或者为图像生成一个不依赖于先前插入行的 UID 的名称。

仍在寻找,但我想知道是否有其他人遇到过此类问题,或者可以为我指出

最佳解决方案的方向 SWK

So here's my problem:

I have an article submission form with an optional image upload field.

When the user submits the form - this is roughly what happens:

if($this->view->form->isValid($_POST){

$db->beginTransaction();
try{
    // save content of POST to Article table 
    if(!$this->_saveArticle($_POST)){
         return;
        }

    // resize and save image using ID generated by previous condition
    if(!$this->_saveImage($_FILES){            
        $db->rollback();
        return;
        }

    // update record if image successfully generated
    if(!$this->_updateArticle(){
        $db->rollback();
        }
    $db->commit();
    }
}catch (Exception $e){
    $db->rollback()
}

All Models are saved using mappers, which automate "UPSERT" functionality by checking for the existence of a surrogate key

public function save($Model){
   if(!is_null($Model->id_article){
       $Mapper->insert($Model->getFields());
       return;
    }
    $Mapper->update($Model->getFields(),$Model->getIdentity());
}

The article table has a composite UNIQUE index of ID,Title and URL. In addition, I'm generating a UID that gets added to the ID field of the Model prior to insert (instead of auto-incrementing)

When I try to execute this, it runs fine for the first article inserted into the table - but subsequent calls (with radically different input) triggers a DUPLICATE KEY error. MySQL throws back the ID generated in condition 1 (_saveArticle) and complains that the key already exists...

I've dumped out the Model fields (and the condition state - i.e. insert | update) and they proceed as expected (pseudo):

inserting!
id = null
title = something 
content = something
image = null

updating!
id = 1234123412341234
title = something
content = something else
image = 1234123412341234.jpg

This row data is not present in the database.

I figure this could be one of a few things:

1: I'm loading a secondary DB adapter on user login, allowing them to interface with several sites from one login - this might be confusing the transaction somehow

2: It's a bug of some description in the Zend transaction implementation (possibly triggered by 1)

3: I need to replace the save() with an INSERT ... ON DUPLICATE

4: I should restructure the submission process, or generate a name for the image that isn't dependent on the UID of the previously inserted row.

Still hunting, but I was wondering if anyone else has encountered this kind of issue or could point me in the direction of a solution

best SWK

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若言繁花未落 2024-10-25 06:21:55

好的 - 只是为了记录,这是完全可能的。问题出在我的应用程序架构中。我在处理持久性的 Mapper 类中捕获异常 - 然后查询它们以返回布尔状态,从而中断该过程。这反过来又破坏了 try/catch 循环,从而阻止插入/更新正常工作。
总结一下 - 是的 - 您可以在单个事务中插入和更新同一行。我已勾选社区维基以取消代表

OK - just for the record, this is entirely possible. The problem was in my application architecture. I was catching Exceptions in my Mapper classes that were handling persistence - and then querying them to return boolean states and thus interrupt the process. This was in turn breaking the try/catch loop which was preventing the insert/update from working correctly.
To summarise - Yes - you CAN insert and update the same row in a single transaction. I've ticked community wiki to cancel rep out

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文