Isso não é verdade. Ele retornará uma linha aleatória. Na prática, geralmente é a primeira linha na ordem da chave primária, mas não há garantia. Bancos de dados diferentes do MySQL não permitem essa prática e gerarão um erro.
De qualquer forma, uma maneira de recuperar o maior ID de mensagens não lidas é juntando-se à tabela de mensagens duas vezes. A segunda junção procura apenas mensagens não lidas. Por exemplo:
SELECT max(msg.ID) as MaxID
, messages.from
, max(unread.ID) as MaxUnreadID
, users.userName
FROM users
join messages msg
on users.ID = msg.from
and messages.to = ?
left join
messages unread
on users.ID = unread.from
and messages.to = ?
and unread.read = 0
GROUP BY
users.ID
, users.userName