【问题标题】:Fetch a Unique Number from a file containing list of numbers concurrently从同时包含数字列表的文件中获取唯一数字
【发布时间】:2011-10-17 08:44:12
【问题描述】:

我有一个文件中唯一编号的列表。每当我网站的用户发出请求时,我都需要从该列表中获取一个值,这样其他用户就不会获得相同的值。可能有许多并发请求,因此主要问题是保证没有两个用户获得相同的值。我并不关心性能,因为用户在发出请求后不会期望任何回复,因此一切都可能在后台发生。根据我的阅读,这可以使用文件锁来实现,或者我可以将数据存储在数据库中并使用数据库锁。我只是想知道做这件事的最佳方法是什么。我正在使用 postresql 作为我的数据库,并且想知道这是否可以使用我在序列中存储当前行号的序列来完成,以便我的程序知道从数据库中读取哪一行。但是我再次不确定如何防止多个进程在其中任何一个有机会更新它之前读取同一行。

【问题讨论】:

    标签: database postgresql concurrency unique file-locking


    【解决方案1】:

    数据库实际上并没有做很多事情,但是它们所做的事情,它们做得很好。特别是,它们处理对数据的并发访问。您可以利用它来发挥自己的优势:

    • 创建表:create table special_number (id serial, num varchar(100) not null);
    • 确保唯一性:create unique index special_number_num on special_number(num);
    • 使用 COPY 将您的数字加载到表格中,让 id 自动从 1 开始计数
    • 创建序列:create sequence num_seq;
    • 使用 postgres 的 nextval 函数保证并发安全这一事实,以安全地从列表中选择一个数字:select num from special_number where id = (select nextval('num_seq'));。如果您的数字用完,这将返回 null

    这种方法是 100% 安全和简单的 - postgres 作为数据库的内部优势可以完成所有繁重的工作。

    这是从上面提取的 SQL:

    create table special_number (id serial, num varchar(100) not null);
    create unique index special_number_num on special_number(num);
    copy special_number(num) from '/tmp/data.txt'; -- 1 special number per file line
    create sequence num_seq;
    select num from special_number where id = (select nextval('num_seq'));
    

    此 SQL 已在 postgres 上进行了测试,并且可以按预期工作。

    【讨论】:

    • 非常感谢您的回答,我只是对此表示怀疑。表 special_number 的所有者 ID 需要什么。
    • @Bohemian 也是,序列并不总是按连续顺序返回数字,这不是真的,这将导致特殊数字表中的某些 id 永远不会是用户。在这种情况下有什么解决方案或如何确保序列 nextval 函数总是按顺序返回 id。
    • @Bohemian 我在当前代码中面临的另一个问题是select num from special_number where id = nextval('num_seq') 返回表中的所有特殊数字。我尝试使用限制 1,但问题是序列更新为 len(特殊数字表),因为 nextval 为每个条目调用一次。我怎么能用你的方法克服这个问题
    • @Bohemian 我在当前代码中面临的另一个问题是 select num from special_number where id = nextval('num_seq') 返回表中的所有特殊数字。我尝试使用限制 1,但问题是序列更新为 len(特殊数字表),因为 nextval 为每个条目调用一次。我改用select num from special_number where id = (Select nextval('num_seq')); 克服了这个问题。还是谢谢
    • @RiteshKadmawala - 请参阅更新的答案,其中包含所有 cmets 的答案。您选择每一行是对的:将 SQL 更改为 ... where id = (select nextval('num_seq')) 进行修复 - 请参阅答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    相关资源
    最近更新 更多