The only data closest to an explanation provided in own documentation is that the change works if the record comes from a "derived" table, as in the example below, and that this is due to the fact that the derived data is materialized in a temporary table:
UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS dt ...);
Extrapolating from this information, this behavior may be a result of the need to avoid conflicting Locks. An UPDATE from a SELECT becomes impossible because the engine does not allow you to obtain a unique lock for a record that is already locked from another transaction.
Thinking this way the above example works because, when faced with a "sub-subselect", the optimizer decides materialize the query in temporary table: the record that receives read lock is a copy, in another location, of the one that will receive exclusive lock for UPDATE, avoiding conflict.
That said, I recognize that this picture I created doesn’t make much sense =/. A documentation of Innodb It is very detailed when emphasizing that the engine supports multiversioning of tuples and the four lock isolation levels, do not have to not do this type of operation normally as in Postgresql, Oracle and the like. I can only believe that this is a remnant of Myisam implementation since pre-5.5.5 versions, since the only type of lock supported by this engine is the whole table.
Mariadb has the same restriction: https://mariadb.com/kb/en/the-mariadb-library/subquery-limitations/
– Victor Stafusa
@Victorstafusa is because Maria DB is almost a copy of mysql, oracle bought mysql, ai a galera do mysql fez o Maria DB.
– Wictor Chaves
@Wictorchaves Yes, exactly. The creator of them is the father of two daughters (My and Maria) and a son (Max). And created a Database Manager System for each of them (Mysql, Mariadb and Maxdb). It’s not every day you meet a father who does it for your children, right?
– Victor Stafusa
Related to the International OS: https://stackoverflow.com/q/23853453/4438007
– Jefferson Quesado