php - PHP/MySQL - 在哪里可靠地处理插入自动重新请求(锁定表) - 客户端或服务器?
问题描述
我有这样的功能,并希望在尝试失败时自动处理插入(取决于错误原因) - 它必须是锁定条件。
这是一个企业应用程序,因此我不依赖客户端服务器之间的大量流量,但仍需要可靠地处理插入。
我应该在哪里放置自动重新提交逻辑(api 请求,或在实际的 php 代码中)以及如何实现它?
public function createOne($params = [])
{
$sql = "insert
into actionitems(
actionitemid,
assignorid,
ownerid,
altownerid,
duedate,
ecd,
criticality,
actionitemtitle,
actionitemstatement,
closurecriteria
)
values(
:actionitemid
:assignorid,
:ownerid,
:altownerid,
:duedate,
:ecd,
:criticality,
:actionitemtitle,
:actionitemstatement,
:closurecriteria
)";
try
{
$this->db->beginTransaction();
$this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$locksql = $this->db->query("lock tables actionitem write");
$statement = $this->db->prepare($sql);
$statement->execute([
':actionitemid' => $params['actionitemid'],
':assignorid' => $params['assignor'],
':ownerid' => $params['owner'],
':altownerid' => $params['altowner'],
':duedate' => $params['duedate'],
':ecd' => $params['ecd'],
':criticality' => $params['criticality'],
':actionitemtitle' => $params['actionitemtitle'],
':actionitemstatement' => $params['actionitemstatement'],
':closurecriteria' => $params['closurecriteria'],
]);
return json_encode(['Result' => 'Success'], JSON_PRETTY_PRINT);
$this->db->commit();
}
catch (PDOExcetption $e)
{
$this->db->rollBack();
return json_encode(['Result' => 'Action Item Was Not Created ' , 'Message' => $e->getMessage(0)]);
}
}
解决方案
我会在 PHP 中做这样的事情:
public function createOne($params = [])
{
// this should be set right after connecting - not here
$this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$sql = "insert into actionitems ... ";
$statement = $this->db->prepare($sql);
for ($attempts = 10; $attempts > 0; --$attempts) {
try {
$this->db->beginTransaction();
$this->db->exec("lock tables actionitem write");
$statement->execute($params);
$this->db->commit();
return json_encode(['Result' => 'Success'], JSON_PRETTY_PRINT);
} catch (PDOExcetption $e) {
$this->db->rollBack();
if ($attempts == 1) { // this is the last attempt
return json_encode(['Result' => 'Action Item Was Not Created ' , 'Message' => $e->getMessage(0)]);
} else {
// do nothing and retry
}
}
}
}
笔记:
正如我在评论中所写 - 我不在乎它为什么会失败(因为它应该是一种非常罕见的情况)并且只是捕获异常并重试。
我不知道您为什么要锁定表格以进行简单的插入。我将其保留在答案中,但我不知道为什么简单的插入会失败。至少在 InnoDB 上它不应该,否则任何尝试都会失败。
我还建议使用第三方库。例如,使用 Laravel 的数据库库,它可能看起来像这样:
public function createOne($params = [])
{
$attempts = 10;
try {
$this->db->transaction(function () use ($params) {
$this->db->statement("lock tables actionitem write");
$this->db->table('actionitems')->insert($params);
}, $attempts);
return json_encode(['Result' => 'Success'], JSON_PRETTY_PRINT);
} catch (Exception $e) {
return json_encode(['Result' => 'Action Item Was Not Created ' , 'Message' => $e->getMessage(0)]);
}
}
更少的代码通常会导致更少的错误。
如果您不想使用第三方库,您也可以自己编写该函数(例如在 trait 中)。你可以在这里查看他们在 laravel 中是如何做到的。
推荐阅读
- javascript - 如何使用 axios 获取流
- javascript - jQuery Ajax `success:` 后显示成功消息并重新加载
- android - 将前台服务与 PlayerView UI 同步?
- php - 致命错误:未捕获的 PDOException:SQLSTATE [23000]:违反完整性约束:1452 无法添加或更新子行:
- apache-kafka - Kafka Consumer endOffsets() 未返回最后一个偏移量
- amazon - Lex + Connect 无法使用检查联系人属性块获取“DialogueState”属性以匹配
- azure-synapse - AAS 刷新问题:为 SQL 源提供的凭据无效
- python - 使用 python 将不规则数据聚合为月平均数天数
- python - 如何在 Pandas 中使用 group_by 函数计算加权平均值
- centos - LFS 错误这些关键程序丢失或太旧:编译 glibc 时生成