Dodaj do tabeli mark_read pola "data_przeczytania" (ustawiane na czas bieżący przy dodawaniu/aktualizacji wiersza) i ew. "post_id" (id ostatniego posta w wątku, który użytkownik miał szansę przeczytać).
Z takiej tabeli nie usuwaj wierszy przy każdym dodaniu posta. Usuwaj je cyklicznie codziennie (albo co miesiąc) dla wpisów o "data_przeczytania" starszym niż 30 dni (zapobiegnie to puchnięciu tabeli, którego się boisz), a jednocześnie uznawaj, że jeśli ostatni post w danym wątku został napisany wcześniej niż 30 dni temu, to każdy użytkownik ma ten temat oznaczony jako przeczytany.
Temat oznaczasz jako nieprzeczytany tylko wtedy, gdy istnieje wpis w "mark_read" o "data_przeczytania" mniejszym niż data dodania ostatniego posta (warto rozszerzyć o taką kolumnę tabelę "tematy", żeby nie obliczać na żywo).
Kolumna "post_id" może posłużyć do wyróżnienia postów napisanych od ostatniej wizyty w wątku, przy czym w przypadku braku wpisu w mark_read takimi postami będą wszystkie posty napisane w ciągu ostatnich 30 dni.
Żeby jeszcze bardziej sobie uprościć życie, proponuję napisanie takiego widoku w bazie danych:
CREATE OR REPLACE VIEW tematy_uzytkownicy AS
SELECT
t.*,
u.id AS user_id,
CASE
WHEN t.data_ostatniego_posta < DATE_SUB(CURDATE(), INTERVAL 30 DAY) THEN 1 -- jesli ostatni post napisano 30 dni temu lub wczesniej - temat przeczytany
WHEN mr.temat_id IS NULL THEN 0 -- w przeciwnym razie jesli nie ma wpisu w mark_read - temat nieprzeczytany
WHEN mr.data_przeczytania < t.data_ostatniego_posta THEN 0 -- lub jesli jest wpis, ale data przeczytania jest starsza niz data dodania ostatniego posta - temat nieprzeczytany
ELSE 1 -- w przeciwnym razie przeczytany
END AS czy_przeczytany
FROM tematy t JOIN uzytkownicy u LEFT JOIN mark_read mr ON (mr.temat_id = t.id AND mr.user_id = u.id)
Potem odpytujesz widok np. takim zapytaniem:
$sql = "SELECT * FROM tematy_uzytkownicy WHERE user_id = '$user_id'";
I otrzymujesz wszystkie tematy z punktu widzenia tego użytkownika, a w kolumnie "czy_przeczytany" masz zero-jedynkową informację o tym czy dany użytkownik przeczytał temat czy nie (i czy nie należy go np. pogrubić na liście).