MySQL UPDATE和SELECT一次传递

我有一个任务执行MySQL表,每行有单个任务的参数。
有很多工人应用程序(可能在不同的机器上),在循环中执行任务。
应用程序使用MySQL的本地C API访问数据库。

为了拥有一个任务,一个应用程序做这样的事情:

  • 生成一个全球唯一的ID(为了简单起见,我们假设它是一个数字)

  • UPDATE tasks
    SET guid = %d
    WHERE guid = 0 LIMIT 1

  • SELECT params
    FROM tasks
    WHERE guid = %d

  • 如果最后一个查询返回一行,我们拥有它,并有参数运行

有没有一种方法可以在一次调用服务器中实现相同的效果(即“拥有”一行并获取其参数)?

试试这个

 UPDATE `lastid` SET `idnum` = (SELECT `id` FROM `history` ORDER BY `id` DESC LIMIT 1); 

上面的代码为我工作

你可以创build一个程序来做到这一点:

 CREATE PROCEDURE prc_get_task (in_guid BINARY(16), OUT out_params VARCHAR(200)) BEGIN DECLARE task_id INT; SELECT id, out_params INTO task_id, out_params FROM tasks WHERE guid = 0 LIMIT 1 FOR UPDATE; UPDATE task SET guid = in_guid WHERE id = task_id; END; BEGIN TRANSACTION; CALL prc_get_task(@guid, @params); COMMIT; 

如果你正在寻找一个单一的查询,那么它不会发生。 UPDATE函数专门返回已更新的项目数。 同样,SELECT函数不会改变一个表,只返回值。

使用一个过程确实会把它变成一个单一的function,如果locking是你关心的话,它可以很方便。 如果你最关心的是networkingstream量(即:传递太多的查询),那么使用该过程。 如果你关心的是服务器重载(即:数据库工作太困难),那么过程的额外开销可能会使事情变得更糟。

我不知道单个呼叫部分,但是你所描述的是一个锁。 锁是关系数据库的一个重要组成部分。

我不知道locking行,读取它,然后在MySQL中更新它的细节,但是阅读一下mysqllocking文档,你可以做各种基于锁的操作。

锁的postgres文件有一个很好的例子,描述了你想要做什么:locking表,读取表,修改表。

 UPDATE tasks SET guid = %d, params = @params := params WHERE guid = 0 LIMIT 1; 

它将返回1或0,这取决于值是否有效更改。

 SELECT @params AS params; 

这只是从连接中selectvariables。

来自: 这里

我有完全相同的问题。 我们结束了使用PostreSQL,而UPDATE ... RETURNING

可选的RETURNING子句会导致UPDATE根据实际更新的每一行计算并返回一个或多个值。 可以计算任何使用表格的列和/或FROM中提到的其他表格的expression式。 使用表格列的新(更新后)值。 RETURNING列表的语法与SELECT的输出列表的语法相同。

例如: UPDATE 'my_table' SET 'status' = 1 WHERE 'status' = 0 LIMIT 1 RETURNING *;

或者,在你的情况: UPDATE 'tasks' SET 'guid' = %d WHERE 'guid' = 0 LIMIT 1 RETURNING 'params';

对不起,我知道这并没有回答MySQL的问题,只是切换到PostgreSQL可能并不容易,但这是我们发现的最好的方法。 甚至6年后,MySQL仍然不支持UPDATE ... RETURNING 。 它可能会在未来某个时候添加,但现在MariaDB只有DELETE语句 。

编辑 :有一个任务(低优先级) 添加UPDATE ... RETURNING支持MariaDB 。