使用 perl 处理数据 - 选择使用 mysql 进行更新使用
我有一个表存储需要处理的数据。我的表中有 id、状态、数据。我目前正在浏览并选择 id、data,其中 status = #。然后,我在选择后立即进行更新,更改状态 # 以便不会再次选择它。
我的程序是多线程的,有时我得到的线程会抓取相同的 id,因为它们都在彼此相对接近的时间查询表,从而导致抓取相同的 id。我研究了 select for update,但是,我要么查询错误,要么我不明白它的用途。
我的目标是找到一种方法来获取我需要的 id、数据并设置状态,以便没有其他线程尝试获取和处理相同的数据。这是我尝试过的代码。 (我在这里出于展示目的将其全部写在一起。我在程序开始时设置了准备工作,以便每次运行时都不会进行准备,以防万一有人担心)
my $select = $db->prepare("SELECT id, data FROM `TestTable` WHERE _status=4 LIMIT ? FOR UPDATE") or die $DBI::errstr;
if ($select->execute($limit))
{
while ($data = $select->fetchrow_hashref())
{
my $update_status = $db->prepare( "UPDATE `TestTable` SET _status = ?, data = ? WHERE _id=?");
$update_status->execute(10, "", $data->{_id});
push(@array_hash, $data);
}
}
当我运行此程序时,如果执行多次线程,在处理事务数据后尝试执行插入时,我会得到许多重复插入。
我对 mysql 和我所做的研究不是很熟悉,我还没有找到任何真正为我解决这个问题的东西。
谢谢
I have a table that is storing data that needs to be processed. I have id, status, data in the table. I'm currently going through and selecting id, data where status = #. I'm then doing an update immediately after the select, changing the status # so that it won't be selected again.
my program is multithreaded and sometimes I get threads that grab the same id as they are both querying the table at a relatively close time to each other, causing the grab of the same id. i looked into select for update, however, i either did the query wrong, or i'm not understanding what it is used for.
my goal is to find a way of grabbing the id, data that i need and setting the status so that no other thread tries to grab and process the same data. here is the code i tried. (i wrote it all together for show purpose here. i have my prepares set at the beginning of the program as to not do a prepare for each time it's ran, just in case anyone was concerned there)
my $select = $db->prepare("SELECT id, data FROM `TestTable` WHERE _status=4 LIMIT ? FOR UPDATE") or die $DBI::errstr;
if ($select->execute($limit))
{
while ($data = $select->fetchrow_hashref())
{
my $update_status = $db->prepare( "UPDATE `TestTable` SET _status = ?, data = ? WHERE _id=?");
$update_status->execute(10, "", $data->{_id});
push(@array_hash, $data);
}
}
when i run this, if doing multiple threads, i'll get many duplicate inserts, when trying to do an insert after i process my transaction data.
i'm not terribly familiar with mysql and the research i've done, i haven't found anything that really cleared this up for me.
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
作为健全性检查,您使用 InnoDB 吗?除了使用全表锁定来伪造事务外,MyISAM 的事务支持为零。
我不知道你在哪里开始交易。 MySQL 的自动提交选项默认处于打开状态,因此启动事务并稍后提交是必要的,除非您关闭自动提交。
As a sanity check, are you using InnoDB? MyISAM has zero transactional support, aside from faking it with full table locking.
I don't see where you're starting a transaction. MySQL's
autocommit
option is on by default, so starting a transaction and later committing would be necessary unless you turned offautocommit
.看起来您只是依赖数据库锁定机制。我用谷歌搜索了
perl dbilocking
并发现了这个:并不是真的说GIYF因为我对 MySQL 和 DBI 都很新手,但也许你可以通过这种方式找到其他答案。
另一种选择可能如下,只有当您控制访问数据的所有代码时,这才有效。您可以在表中创建
lock
列。当您的代码访问表时(伪代码):不过,这再次相信访问此数据的所有用户/脚本将同意遵循此策略。如果你不能确保这一点,那么这将不起作用。
无论如何,这就是我对该主题的所有知识。祝你好运!
It looks like you simply rely on the database locking mechanisms. I googled
perl dbi locking
and found this:Not really saying GIYF as I am also fairly novice at both MySQL and DBI, but perhaps you can find other answers that way.
Another option might be as follows, and this only works if you control all the code accessing the data. You can create
lock
column in the table. When your code accesses the table it (pseudocode):again though, this trusts that all users/script that access this data will agree to follow this policy. If you cannot ensure that then this won't work.
Anyway thats all the knowledge I have on the topic. Good Luck!