Из документации:
Изменение значений столбцов в существующей строке очень похоже на вставку новой строки:
m := spanner.Update("User", []string{"user_id", "profile"}, []interface{}{UserID, profile}) _, err := client.Apply(ctx, []*spanner.Mutation{m})
Как Spanner понимает, какую строку нужно обновить? Я вижу, что отсутствует пункт WHERE. Использует ли он автоматически некоторые поля в качестве ключа (например, неявный user_id = "...")?

Cloud Spanner автоматически использует первичный ключ таблицы, которую обновляет мутация. Это означает, что вы должны включить все столбцы первичного ключа в мутацию Update. Таким образом, одна мутация Update также обновит только одну строку (и вернет ошибку NOT_FOUND, если строка не существует).
Это также означает, что невозможно обновить значение первичного ключа строки. Вместо этого вы должны удалить строку и вставить новую, если хотите «изменить» значение первичного ключа.
См. https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.v1#mutation для получения дополнительной информации о том, как работают мутации.
И означает ли это, что нельзя обновить первичный ключ?
Правильно, значение первичного ключа не может быть обновлено. Я также добавил ссылку на документацию.
Означает ли это также, что ключевые поля всегда должны быть включены, иначе мутация завершится ошибкой?
да, мутация Update должна включать значение для всех столбцов первичного ключа, в противном случае она не будет выполнена.
Можете ли вы дать ссылку на какую-либо документацию, подтверждающую это, если это возможно?