Mi sono accorto che su uno dei miei siti web, dal 1 Dicembre, Backup & Migrate creava file compressi .gz di dimesione pari a ZERO. Io in genere mantengo 24 Backup del DB proprio x avere sicurezza, in genere sono i backup di circa 3 giorni.
Ho fatto un export manuale del DB non compresso ed ho subito pensato che potesse esserci un problema nel DB.
L'ho compresso con gzip -9 senza particolari problemi, quindi ho fatto un'altro tipo di indagine:
Ho provato a reimportarlo, c'è voluto un casino di tempo xkè è abbastanza grande, finchè l'import si è interrotto con questo errore di sintassi:
ERROR 1064 (42000) at line 44018: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'migliorati','7808','node','1'),('pressando','7808','node','1'),('quasi','7808','' at line 1
a questo punto, con vi, sono andato sulla riga 44018 e c'era un errore proprio in questa forma ('pressando','7808','node','1'). Nel senso che c'era un termine ('parola", 'numero', .... ma poi non indicava 'node','1' e non chiudeva la parentesi. Ho fatto la correzione a mano.
A questo punto, visto che non mi andava di attendere di nuovo altre 44018 righe di import, di cui la maggiorparte sono insert nella tabella node_revisions, ho provato a splittare il file in questo modo:
split -l 40000 dump
Ottenendo così una serie di files.
A questo punto ho ripreso l'import da file in cui è presente la riga che ha causato l'interruzione.
Il risultato è questo immediato messaggio di errore:
ERROR 1062 (23000) at line 1: Duplicate entry 'sera-3072-node' for key 1
Questo mi fa pensare che non posso splittare un dump in maniera arbitraria ma ho bisogno di qualcosa che mi consenta di fare un split del file in modo tale che ogni file abbia all'interno tutto il necessario per essere importato senza errori.
Cosa usare, come fare a splittare correttamente un DB DUMP?
A me interessa solo lo split, poi per l'import ci pensa mysql, questo perchè ho DB molto grandi che diventano sempre più grandi.
In realtà però non è un problema fare l'import di DB grandi da riga di comando, però avere file splittati correttamente consente di intervenire in caso di errori e reimportare, in maniera più agevole e rapida.
La rapidità di import è legata, in buona parte, anche alla quota di memoria disponibile, più è grande + rapido sarà l'import del db. In ogni caso l'import tramite mysql non si interrompe per limiti di ram, al massimo si incasina x limiti di spazio su disco.
Ci sarebbe da indagare sul perchè Drupal ha creato quell'errore di sintassi su indicato in una riga della tabella search_index, ed è proprio quello che sto continuando a fare oltre il problema dello split.
Domanda
mi si è interrotto di nuovo l'import a casusa di un'altro errore di sintassi sempre in una riga della tabella search_index. Stavolta c'era una parentesi aperta, senza alcun contenuto e mai chiusa
A questo punto chiedo:
è possibile importare un db di drupal privo dei dati nelle tabelle search, senza alcuna conseguenza e ricostruendo l'indice delle ricerche in un secondo momento, ad ogni cron?
Allo stesso modo, è cosa buona esportare i DB dei siti web di drupal, senza esportare i contenuti delle tabelle search, per lo stesso motivo su indicato?
http://www.sanisapori.eu
i contenuti estesi sono stati inclusi nel dump ?
Dal proseguio delle analisi si evince che ad un certo punto, il 30 novembre qualcosa nella tabella search_index è andato male.
Tant'è che l'ultimo backup del 30 Novembre non è scompattabile. In più analizzando meglio l'export manuale del DB, questo esporta SOLO fino alla tabella search-index
A questo punto le cose che posso fare sono 2:
Cmq sia, non mi era MAI capitato un problema nella tabella search_index
In effetti potrei anche fare un'altra prova, andare sul sito e dire a drupal di ricostruire il Search Index e dopo vedere che se il nuovo backup è corretto.
Prima di passare ai 2 punti su indicati, provo questa via. Il problema è che x reindicizzare TUTTE le voci, ci vorranno ore. L'importante è avere da parte i vecchi backup.
@Lorenzo: non ho capito cosa intendi x contenuti estesi. In ogni caso nei dump ci sono tutti i dati di tutte le tabelle, quando tutto funziona.
http://www.sanisapori.eu
La casella "contenuti estesi" è visibile in qualsiasi tipo di Page / Finestra di import/export del database PhpMyadmin.
Se l'hai segnata per l'export : è un grande aggravio di dati da trasbordare. E spesso è causa di impossibilità nel dumpare anche troncando, con programmi appositi, il file SQL gzippato da importare in remoto ( il tuo caso).
Io NON ho mai menzionato phpMyAdmin!!...Non serve a nulla phpMyAdmin in questo caso, al massimo lo usi per monitoring.
Se leggi meglio la discussione qui non stiamo parlando di Data Base da 10MB, ma di grosse dimensioni, centinaia e centinaia di MB, ormai tendenti al GB. In tali casi con phpMyAdmin non ci fai nulla di nulla: vedi sparire tutto in una pagina bianca!
Sempre se leggi meglio, noterai che stiamo parlando di interventi da riga di comando.
Cmq è in ogni caso corretta la questione dell'extended insert.
http://www.sanisapori.eu
beh arrangiati Signor SòTutto.
e Cmq questi Toni arrogantelli "valli a usare con qualcun'altro",
con me hai chiuso Qui.
Chiunque voglia collaborare è ben accetto, purchè si rispetti la discussione. Qui si tratta di lavoro e di problemi che possono capitare a chiunque. Risolverli definendo un HowTo strutturato è un aiuto per chiunque usi DrupalItalia.org come punto di riferimento.
Mantenere siti web strutturati di grosse dimensioni, richiede manutenzione continua e script attivi di vario genere che qualcuno realizza e condivide su questo forum. Non è un gioco.
Per cortesia non perdiamoci in banalità e cerchiamo di collaborare x andare avanti in tutte le cose.
http://www.sanisapori.eu
Una potenziale soluzione al problema dello Split di Data Base di grosse dimensioni è questa e può essere applicata in due modi.
impostando a FALSE extended-insert ottieni un ottimo risultato, però ti ritrovi un dump molto + grande del normale, nel mio caso il DB era circa 1/3 + grande.
L'utilizzo invece di --no-create-info=TRUE fa in modo di esportare solo i dati.
Quindi se accoppiamo 2 file (lo schema e i dati senza create table) risolviamo il problema.
Un esempio può essere:
mysqldump -u user -p -d nomedb > schema_db.sql
mysqldump -u user -p nomedb --extended-insert=FALSE --no-create-info=TRUE > data_db.sql
oppure
mysqldump -u user -p nomedb --no-create-info=TRUE > data_db.sql
split -l 500000 data_db.sql
Il problema dove sta?.... Sta nel fatto che Backup&Migrate non consente di usare tali importazioni da interfaccia (non so tramite drush). Questo implica che devi crearti un script apposito da far girare in crontab che esporti lo schema ed esporti solo i dati aggiungendo la data, faccia uno split dei dati per esempio a 500.000 o 1.000.000 di righe x file, comprima ogni file. Poi fare un'altro script o arricchire sempre lo stesso x ripulire la directory dei DUMP di quelli + vecchi di una certa data o numero.
Infine uno script per gestire l'import dei singoli split.
Direi che è un lavoro esagerato. In ogni caso backup&migrate è limitato xkè io con mysql ho esportato TUTTO il db, ma backup&migrate a causa degli errori nella search-index ha esportato solo fino alla search index
http://www.sanisapori.eu
La ricostruzione dell'indice non ha risolto il problema.
Backup&Migrate, continua ad esportare DUMP parziali, troncati che poi va in errore comprimendoli lasciando file.gz con dimesione 0.
Non è un caso isolato... direiche tutti i DB superiori ad un certo volume abbiano queto problema.
Sembra che Backup&Migrate non riesca a fare il Backup di DB superiori a 250MB. O forse che lo script lanciato per il Backup venga troncato dopo un certo tempo o dopo un certo uso della memoria o non so.
Contatterò i manteiner di Backup&Migrate.
http://www.sanisapori.eu
Trovata una soluzione al problema dello Split dei DB di grosse dimensioni.
Perchè preoccuparci di splittare un Dump già effettuato...
Perchè invece non esportiamo una serie di dump parziali, ognuno x ogni singla tabella?
Ecco gli step dell'algoritmo.
Dal test che ho fatto risulta che l'export fatto secondo questo algoritmo specifico, è decisamente rapido, almeno per quel che concerne database da 300MB.
L'import è una cosa estremamente semplice.
l'importante è che il file che fai carire a mysql contenga al suo interno l'elenco dei file delle singole tabelle.
Si può fare!.... quello che mi manca adesso è come ragionare sugli script di manutenzione dei DB di Drupal, affinchè cancellino automaticamente i file è vecchi di una certa data o di un certo numero.
http://www.sanisapori.eu
Ecco un script più che funzionante che sopperisce ai bug di Backup&Migrate scoperti in questi giorni.
Questo script ha delle proprietà molto utili e mirate verso di Data Base di grandi dimensioni. Primo fra tutti lo spit del DB.
Ecco cioè che fa:
La dove Backup&Migrate FALLISCE, questo script non vi lascerà MAI a piedi. Anzi, direi che va utilizzato SEMPRE, allegerendo drupal di Backup&Migrate.
Avrei potuto tentare di creare script utilizzando Drush, ma in passato per lo script che uso per il cronjob, ho notato problemi. Quindi non lo utilizzo x gli script in cron.
In particolare lo script va lanciano ogni n ore tramite Crontab.
#!/bin/bash
DBNAMES="
db1
db2
db3
"
USER=(
user1
user2
user3
)
PASSWORD=(
pass1
pass2
pass3
)
HOST="ip_host"
BACKUP_DIR="directory_backups"
OPTIONS="--default-character-set=utf8 --complete-insert --no-create-info --compact -q"
DATE=`/bin/date '+%y%m%d_%H%M%S'`
#### start script ####
i=0
for DB in $DBNAMES
do
cd ${BACKUP_DIR}
if [ ! -d ${DB} ]; then
mkdir ${DB}
fi
cd ${BACKUP_DIR}/${DB}
RESTORESCRIPT="$BACKUP_DIR/$DB/__restoreData.sql"
echo removing old temporary files if they exists...
rm -f ${BACKUP_DIR}/${DB}/*.sql > /dev/null 2>&1
rm -f ${BACKUP_DIR}/${DB}/*.tar > /dev/null 2>&1
echo 'SET FOREIGN_KEY_CHECKS=0;' > $RESTORESCRIPT
mysqldump --no-data --host=$HOST --user=${USER[${i}]} --password=${PASSWORD[${i}]} $DB > ${BACKUP_DIR}/${DB}/__createTables.sql
echo 'source __createTables.sql;' >> $RESTORESCRIPT
for TABLE in `mysql --host=$HOST --user=${USER[${i}]} --password=${PASSWORD[${i}]} $DB -e 'show tables' | egrep -v 'Tables_in_' `; do
TABLENAME=$(echo $TABLE|awk '{ printf "%s", $0 }')
FILENAME="${TABLENAME}.sql"
echo Dumping $TABLENAME
echo 'source' $FILENAME';' >> $RESTORESCRIPT
mysqldump $OPTIONS --host=$HOST --user=${USER[${i}]} --password=${PASSWORD[${i}]} $DB $TABLENAME > ${BACKUP_DIR}/${DB}/${FILENAME}
done
echo 'SET FOREIGN_KEY_CHECKS=1;' >> $RESTORESCRIPT
echo making tar...
tar -cf ${DATE}_${DB}.tar *.sql > /dev/null 2>&1
echo compressing...
gzip -9 ${DATE}_${DB}.tar > /dev/null 2>&1
echo removing temporary files...
rm -f ${BACKUP_DIR}/${DB}/*.sql > /dev/null 2>&1
rm -f ${BACKUP_DIR}/${DB}/*.tar > /dev/null 2>&1
echo "done with " $DB
let i=i+1
done
Dove sta il vantaggio concreto di splittare di Data Base di grandi dimensioni?
Il primo vantaggio che mi viene in mente è quello in cui se durante l'import del DB qualcosa fallisce per syntax error del dump e il processo si interrompe, sai sicuramente in quale tabella/dump file intervenire manualmente x correggere l'errore e successivamente far partire l'import proprio da dove c'è stata l'interruzione. In questo modo i DB di grandi dimensioni diventano relativamente gestibili.
La cosa brutta semmai è che + grande è il DB + tempo ci vorrà ad importarlo. Già solo un database da 300MB richiede tanto tempo di import xkè le tabelle node_revisions e search_index sono molto grandi.
A questo mi manca uno script per ripuli le directory dei DB dei backup + vecchi di una certa data, oppure contenere in ogni directory solo un certo numero di file ed eliminare di volta in volta il + vecchio.
http://www.sanisapori.eu
Aggiungo una variante allo script, per rimuovere i backup + vecchi di X giorni ed anche tutti gli eventuali file temporanei rimasti nelle directory x vari motivi.
#!/bin/bash
DBNAMES="
db1
db2
db3
"
USER=(
user1
user2
user3
)
PASSWORD=(
pass1
pass2
pass3
)
HOST="ip_host"
BACKUP_DIR="directory_backups"
BACKUP_OLDER="+4"
OPTIONS="--default-character-set=utf8 --complete-insert --no-create-info --compact -q"
DATE=`/bin/date '+%y%m%d_%H%M%S'`
#### start script ####
i=0
for DB in $DBNAMES
do
cd ${BACKUP_DIR}
if [ ! -d ${DB} ]; then
mkdir ${DB}
fi
cd ${BACKUP_DIR}/${DB}
RESTORESCRIPT="$BACKUP_DIR/$DB/__restoreData.sql"
echo removing old temporary files if they exists...
rm -f ${BACKUP_DIR}/${DB}/*.sql > /dev/null 2>&1
rm -f ${BACKUP_DIR}/${DB}/*.tar > /dev/null 2>&1
echo 'SET FOREIGN_KEY_CHECKS=0;' > $RESTORESCRIPT
mysqldump --no-data --host=$HOST --user=${USER[${i}]} --password=${PASSWORD[${i}]} $DB > ${BACKUP_DIR}/${DB}/__createTables.sql
echo 'source __createTables.sql;' >> $RESTORESCRIPT
for TABLE in `mysql --host=$HOST --user=${USER[${i}]} --password=${PASSWORD[${i}]} $DB -e 'show tables' | egrep -v 'Tables_in_' `; do
TABLENAME=$(echo $TABLE|awk '{ printf "%s", $0 }')
FILENAME="${TABLENAME}.sql"
echo Dumping $TABLENAME
echo 'source' $FILENAME';' >> $RESTORESCRIPT
mysqldump $OPTIONS --host=$HOST --user=${USER[${i}]} --password=${PASSWORD[${i}]} $DB $TABLENAME > ${BACKUP_DIR}/${DB}/${FILENAME}
done
echo 'SET FOREIGN_KEY_CHECKS=1;' >> $RESTORESCRIPT
echo making tar...
tar -cf ${DATE}_${DB}.tar *.sql > /dev/null 2>&1
echo compressing...
gzip -9 ${DATE}_${DB}.tar > /dev/null 2>&1
echo removing temporary files...
rm -f ${BACKUP_DIR}/${DB}/*.sql > /dev/null 2>&1
rm -f ${BACKUP_DIR}/${DB}/*.tar > /dev/null 2>&1
echo "=========================================="
echo ${DB} - clean older backup files
echo "=========================================="
echo removing files backup older $BACKUP_OLDER days...
find ${BACKUP_DIR}/${DB} -mtime $BACKUP_OLDER -type f -exec ls {} \;
find ${BACKUP_DIR}/${DB} -mtime $BACKUP_OLDER -type f -exec rm {} \;
let i=i+1
done
Adesso è pronto e l'ho testato talmente tante volte che posso rimuovere Backup&Migrate da tutti i siti web ed ovviamente, a differenza di Backup&Migrate, lo posso applicare anche a CiviCRM ed a qualsiasi altro DB.
Lo script viene lanciato in crontab ogni 4 ore con la riga che segue
0 */4 * * * /~/scripts/drupal-backups.sh 2>&1 > /~/logs/drupal-backups.log
Lo script è concluso, e si accettano suggerimenti per migliorarlo.
http://www.sanisapori.eu
Per fare il Restore del DB basta scompattare uno dei Archive .tat.gz. Questa operazione riempirà la directory di file sql ma non importa perchè comunque lo script su indicato penserà a fare pulizia al prossimo lancio.
A questo punto usate l'istruzione qui indicata per importare tutti i DUMP.
$ mysql -uroot -pYourPassword -h YourHost YourDatabaseName < __restoreData.sql
il file __restoreData.sql contiene tutte le source, cioè l'elenco di tutti i singoli dump da reimportare. In caso di problemi durante l'import il file __restoreData.sql può essere modificato al fine di far ripartire l'import dal punto in cui è stato interrotto senza dover ricominciare tutto da capo.
Si consiglia sempre di importare in un DB nuovo, inutile fare l'import sul db già esistente.
http://www.sanisapori.eu