gpt4 book ai didi

php - MySQL 和 PHP : Atomicity and re-entrancy of a PHP code block executing two subsequent queries - how dangerous?

转载 作者:行者123 更新时间:2023-11-29 01:47:30 24 4
gpt4 key购买 nike

在 MySQL 中,我必须检查 select 查询是否返回了任何记录,如果没有,我将插入一条记录。恐怕 PHP 脚本中的整个 if-else 操作并不像我希望的那样原子化,即在某些情况下会中断,例如,如果在需要处理同一记录的地方调用脚本的另一个实例:

if(select returns at least one record)
{
update record;
}
else
{
insert record;
}

我这里没有使用事务,自动提交是开启的。我正在使用 MySQL 5.1 和 PHP 5.3。该表是 InnoDB。我想知道上面的代码是否不是最理想的并且确实会中断。我的意思是相同的脚本被两个实例重新输入,并出现以下查询序列:

  1. 实例1尝试选择记录,没有找到,进入插入查询 block
  2. 实例2尝试选择记录,没有找到,进入插入查询 block
  3. 实例1尝试插入记录,成功
  4. 实例 2 尝试插入记录,失败,自动中止脚本

意味着实例 2 将中止并返回错误,跳过插入查询语句后的任何内容。我可以让错误不是致命的,但我不喜欢忽略错误,我更想知道我的恐惧是否真的存在。

更新:我最后做了什么(这样可以吗?)

有问题的表有助于限制(允许/拒绝,实际上)应用程序发送给每个收件人的消息量。系统在 Z 期间内不应向收件人 Y 发送超过 X 条消息。该表[概念上]如下:

create table throttle
(
recipient_id integer unsigned unique not null,
send_count integer unsigned not null default 1,
period_ts timestamp default current_timestamp,
primary key (recipient_id)
) engine=InnoDB;

[有点简化/概念] PHP 代码块应该执行原子事务,维护表中的正确数据,并根据节流状态允许/拒绝发送消息:

function send_message_throttled($recipient_id) /// The 'Y' variable
{
query('begin');

query("select send_count, unix_timestamp(period_ts) from throttle where recipient_id = $recipient_id for update");

$r = query_result_row();

if($r)
{
if(time() >= $r[1] + 60 * 60 * 24) /// The numeric offset is the length of the period, the 'Z' variable
{/// new period
query("update throttle set send_count = 1, period_ts = current_timestamp where recipient_id = $recipient_id");
}
else
{
if($r[0] < 5) /// Amount of messages allowed per period, the 'X' variable
{
query("update throttle set send_count = send_count + 1 where recipient_id = $recipient_id");
}
else
{
trigger_error('Will not send message, throttled down.', E_USER_WARNING);
query('rollback');
return 1;
}
}
}
else
{
query("insert into throttle(recipient_id) values($recipient_id)");
}

if(failed(send_message($recipient_id)))
{
query('rollback');
return 2;
}

query('commit');
}

好吧,忽略 InnoDB 死锁发生的事实,这很好,不是吗?我不是在捶胸顿足,但这只是我能做的性能/稳定性的最佳组合,除了使用 MyISAM 和锁定整个表之外,我不想这样做,因为更新/插入比更频繁选择。

最佳答案

您似乎已经知道问题的答案,以及如何解决您的问题。这是一个真实的问题,您可以使用以下方法之一来解决它:

  • 选择...进行更新
  • 插入 ... 在重复 key 更新时
  • 交易(不要使用 MyIsam)
  • 表锁

关于php - MySQL 和 PHP : Atomicity and re-entrancy of a PHP code block executing two subsequent queries - how dangerous?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3104365/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com