MySQL UPDATE and SELECT in one pass

后端 未结 6 1289
轮回少年
轮回少年 2020-11-28 14:05

I have a MySQL table of tasks to perform, each row having parameters for a single task.
There are many worker apps (possibly on different machines), performing tasks in

相关标签:
6条回答
  • 2020-11-28 14:47

    I have the exact same issue. We ended up using PostreSQL instead, and UPDATE ... RETURNING:

    The optional RETURNING clause causes UPDATE to compute and return value(s) based on each row actually updated. Any expression using the table's columns, and/or columns of other tables mentioned in FROM, can be computed. The new (post-update) values of the table's columns are used. The syntax of the RETURNING list is identical to that of the output list of SELECT.

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

    Or, in your case: UPDATE 'tasks' SET 'guid' = %d WHERE 'guid' = 0 LIMIT 1 RETURNING 'params';

    Sorry, I know this doesn't answer the question with MySQL, and it might not be easy to just switch to PostgreSQL, but it's the best way we've found to do it. Even 6 years later, MySQL still doesn't support UPDATE ... RETURNING. It might be added at some point in the future, but for now MariaDB only has it for DELETE statements.

    Edit: There is a task (low priority) to add UPDATE ... RETURNING support to MariaDB.

    0 讨论(0)
  • 2020-11-28 14:58

    try like this

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

    above code worked for me

    0 讨论(0)
  • 2020-11-28 14:58

    You may create a procedure that does it:

    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;
    
    0 讨论(0)
  • 2020-11-28 15:03

    I don't know about the single call part, but what you're describing is a lock. Locks are an essential element of relational databases.

    I don't know the specifics of locking a row, reading it, and then updating it in MySQL, but with a bit of reading of the mysql lock documentation you could do all kinds of lock-based manipulations.

    The postgres documenation of locks has a great example describing exactly what you want to do: lock the table, read the table, modify the table.

    0 讨论(0)
  • 2020-11-28 15:04
    UPDATE tasks
    SET guid = %d, params = @params := params
    WHERE guid = 0 LIMIT 1;
    

    It will return 1 or 0, depending on whether the values were effectively changed.

    SELECT @params AS params;
    

    This one just selects the variable from the connection.

    From: here

    0 讨论(0)
  • 2020-11-28 15:10

    If you are looking for a single query then it can't happen. The UPDATE function specifically returns just the number of items that were updated. Similarly, the SELECT function doesn't alter a table, only return values.

    Using a procedure will indeed turn it into a single function and it can be handy if locking is a concern for you. If your biggest concern is network traffic (ie: passing too many queries) then use the procedure. If you concern is server overload (ie: the DB is working too hard) then the extra overhead of a procedure could make things worse.

    0 讨论(0)
提交回复
热议问题