在同一事务中插入和更新同一行? (MySQL)
所以这是我的问题:
我有一个带有可选图像上传字段的文章提交表单。
当用户提交表单时,大致会发生以下情况:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的 - 只是为了记录,这是完全可能的。问题出在我的应用程序架构中。我在处理持久性的 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