Вторая половина #2731. `_upsert_listing_source` вызывается ПОСТРОЧНО из save_listings
(hook _link_listing_to_house), транзакция batch'а коммитится один раз в конце, поэтому
NOW() == transaction_timestamp() давал одну метку на весь вызов: прод 2026-08-06 по
часам — 219 строк / 1 метка, 235/1, 297/1, 150/1 и так каждый час.
Чинится вместе с listings.scraped_at/last_seen_at, а не отдельно. Сегодня
listings.last_seen_at = listing_sources.last_seen_at у 100% пар (2407 из 2407 за сутки)
именно потому, что обе берут одну транзакционную метку. Починить только listings —
значит оставить вторую замороженной на старте batch'а и вырастить расхождение с
миллисекунд (честная разница двух соседних записей) до длительности прогона.
matched_at / last_seen_at / last_scraped_at пишутся ОДНИМ statement'ом, поэтому
statement_timestamp() даёт им одинаковое значение — их равенство сохраняется.
clock_timestamp() развёл бы их на микросекунды.
Refs #2731