La query non riesce perché non puoi modificare una tabella e selezionare da quella stessa tabella in una sottoquery.
Vedi Sintassi della sottoquery
Penso che tu possa aggirare questo problema con qualche trucco JOIN:
UPDATE meterreadings AS tgt
INNER JOIN (
SELECT * FROM meterreadings
WHERE meterreadingtype_id = 2
) AS src
ON tgt.meterreadingdate = src.meterreadingdate
AND tgt.location_id = src.location_id
AND tgt.created = src.created
AND tgt.asset_id = src.asset_id
SET tgt.meterreading = src.meterreading
Non sono un esperto di MySQL, ma credo che funzioni perché MySQL elabora prima la sottoquery e memorizza il risultato in memoria come una tabella temporanea, che non cambia durante l'AGGIORNAMENTO. Un effetto collaterale di questo è che se il risultato della sottoquery è grande, allora consumerai un sacco di (o esaurirai) la memoria.
L'unico modo (per quanto ne so) per aggirare il problema della memoria è ridurre la sottoquery utilizzando criteri che non sono direttamente correlati alla destinazione dell'aggiornamento. Ad esempio, se dovessi eseguire questi aggiornamenti come parte di un processo notturno, fai in modo che il SELECT interno restituisca solo le righe create nelle ultime ~24 ore.