Hej - przejąłem niedawno projekt w którym wersjonowanie wpisów wygląda następująco:
tworzony jest wpis w tabeli versions
która ma postać: id, page_id, user_id, create_date
oraz tworzony jest plik na dysku z serializowanymi danymi odpowiadającymi rekordowi o id page_id.
Wszystko działa ok wersje się zapisują i można je przywracać. Nałożone jest dodatkowo ograniczenie do 5 wersji wstecz. I tu jest problem - okazało się że skrypt napisany jest nieco wadliwie - usuwa stare wersję z bazy ale nie z dysku - w ten sposób powstała niespójność danych w bazie i na dysku. Plików wersji jest obecnie 12 mln a wpisów w bazie 2mln. Pytanie czy jest jakiś sensowny sposób no usunięcie plików z dysku których odpowiedników nie ma w bazie?
Ten pomysł z ręcznym trzymaniem danych na dysku to żart, tak? :|
Trzymanie wersji jest zrobione tak jak opisałem - póki co mechanizm musi zostać jak jest - szukam sposobu na szybkie usunięcie plików których odpowiedników nie ma w bazie
Jak mają się nazwy plików do atrybutów z tabeli versions? Page_ID jest nazwą pliku czy fragmentem nazwy?
page_id jest fragmentem nazwy pliku
12mln plików to jest za dużo jak na excela.
Ja bym zrobił tak:
- przygotował plik CSV zawierający listę plików z file systemu + informację o page_id z pliku, czyli pliku o strukturze:
scieżka absolutna do pliku,page_id
- Załadował plik do bazy danych do jakiejś tabeli tymczasowej o kolumnach:
file_name
page_id
- Zrobił anti-joina między tabelą tymczasową i tabelą version. Tak by odfiltrować z listy plików te, dla których brakuje wpisu w bazie:
select 'rm '||file_name from tabelka_tymczasowa t where not exists (select 1 from version v where t.page_id=t.page_id);
Wynik zapytania, to tak naprawdę będzie lista komend shellowych do usuwania plików.
- Uruchomił wygenerowany plik:
chmod +x mojMegaSkrypt.sh
./mojMegaSkrypt.sh
Pkt. 1 pod linuxem realizuje się trywialnie, np. jednolinijkowcem:
find /proc -type f | awk -F/ '{print $0";"$NF}'
I otrzymać coś w stylu:
/proc/2510/auxv,auxv
/proc/2510/status,status
/proc/2510/personality,personality
/proc/2510/limits,limits
/proc/2510/sched,sched
/proc/2510/autogroup,autogroup
/proc/2510/comm,comm
Jak masz nazwę pliku: FOO_XYZ_<PAGE_ID>_<DATA>.html czy coś tam, to trzeba inaczej wycinać ten <PAGE_ID>. sed/awk Twoim przyjacielem.
Pkt. 3 wyprodukuje coś w stylu:
rm /proc/2510/status
rm /proc/2510/personality
rm /proc/2510/limits
Katalog /proc
jest oczywiście poglądowo.
Szkic masz. Produkcyjnie zrobiłbym to inaczej ;) Do skonstruowania tej listy użyłbym perla i napisał te kilka linijek więcej. (12m plików to jednak może być nieco za dużo jak na zestaw narzędzi shellowych, np. ls wymiękał mi przy katalogach z 1 mln plików).