«

»

giu 14

Una classe Java per effettuare il backup di un database Mysql (v 2.0)

Quando si sviluppa un applicazione che permette di interagire e modificare un database può essere utile prevedere una funzione che permetta di effettuare velocemente e con un solo click il backup completo dell’intero database (dati, struttura, trigger e stored procedure).

Questa classe fa esattamente questo, e a differenza dei molti snippet che si trovano sul web è completa e autosufficente e documentata con javadoc, necessita soltanto della presenza nel sistema del comando “mysqldump” (presenza che viene verificata dalla classe stessa).

La classe avvia un istanza di mysqldump e permette di salvarne l’output in dei file di testo ,in un unico file zip o eventualmente in una stringa

A differenza della versione precedente ( descritta qui )  questa versione permette di importare/esportare anche tabelle che hanno vincoli di integrità relazionale.
Per fare questo disabilita il check delle Costraint , esegue l’intera importazione all’interno di una transazione, e poi le riattiva.
Questo comportamento può essere attivato con checkConstraint=false
Il comportamento di default è identico alla versione precedente

il file può essere scaricato da QUI

vediamo un esempio di utilizzo:

package cavia;

import darshan.util.MysqlBackup;
public class Main {

 public static void main(String[] args) {
 MysqlBackup b= new MysqlBackup("127.0.0.1", "3306", "root", "root", "darshan");
 b.checkConstraint=false;
 b.all_to_zip("/home/darshan/Scrivania/post/dump.zip");
 System.out.println("Done");
 }

la classe viene istanziata con MysqlBackup(ip, porta, user, password, database) , poi con b.checkConstraint=false; disabilito il check delle costraint e con all_to_zip eseguo il dump in un file zip, per le altre funzioni affidatevi al javadoc che trovate anche qui
di seguito il sorgente

package darshan.util;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 *
 * @author Vicenzo La Spesa
 * @version 2.0
 * 14/06/2011
 * http://www.thedarshan.com
 */
public class MysqlBackup {

    private static String head="SET AUTOCOMMIT=0; SET FOREIGN_KEY_CHECKS=0;\n";
    private static String tail="SET FOREIGN_KEY_CHECKS=1;COMMIT;SET AUTOCOMMIT=1;\n";

    /**
     * permette di abilitare/disabilitare il controllo dell'integrità referenziale
     * durante la fase di creazione, nel caso sia disabilitata è possibile inserire
     * tabelle che hanno riferimenti in qualsiasi ordine.
     */
    public boolean checkConstraint=true;

    private String host, port, user,password, db;

 /**
  * boolean installed()
  * verifica se è possibile avviare mysqldump,<br>
  * La verifica viene effettuata avviando "mysqldump --help" e cercando la stringa
  * "mysqldump al suo interno"
  * @return true se il comando è disponibile, false altrimenti
  */
 public boolean installed(){
        try {
            Process run = Runtime.getRuntime().exec("mysqldump --help");
            InputStream in = run.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String out = br.readLine();
            int n=out.indexOf("mysqldump");
            br.close();
            in.close();
            if(n >-1 && n<2) return true;
        } catch (IOException ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
        }
    return false;
 }

 /**
  * @param host
  * @param port
  * @param user
  * @param password
  * @param db
  * @return una stringa con il backup del database, <br> una stringa vuota se scrive sullo stream
  * @throws java.lang.Exception
  *
  * esegue il backup dei dati su stringa,o su uno stream dato come argomento <br>
  * è un overload
  */
 private String getData(String host, String port, String user,
                        String password, String db) throws Exception{
     return getData(host, port, user, password, db,null);

 }
 private String getData(String host, String port, String user,
                        String password, String db, OutputStream stream) throws Exception {
  Process run = Runtime.getRuntime().exec(
                       "mysqldump --host=" + host + " --port=" + port +
                       " --user=" + user + " --password=" + password +
                       " --compact --complete-insert --extended-insert " +
                       "--skip-comments --skip-triggers " + db);
  InputStream in = run.getInputStream();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  StringBuilder temp = new StringBuilder();
  DataOutputStream output=new DataOutputStream(stream);

  String buffer;

  if(!checkConstraint)output.writeBytes(head);
  while ((buffer = br.readLine()) != null) {
      if(stream!=null){
            output.writeBytes(buffer+"\n");
      }else{
                temp.append(buffer).append("\n");
      }

  }
  if(!checkConstraint)output.writeBytes(tail);

  br.close();
  in.close();

  return temp.toString();//se scrive sullo stream è una stringa vuota
 }

 /**
  *
  * @param host
  * @param port
  * @param user
  * @param password
  * @param db
  * @return una stringa con la struttura del db
  * @throws java.lang.Exception
  *
  * estrae la struttura del db e le stored procedure
  */
 static private String getRoutine(String host, String port, String user,
                           String password, String db) throws Exception {
  Process run = Runtime.getRuntime().exec(
                       "mysqldump --host=" + host + " --port=" + port +
                       " --user=" + user + " --password=" + password +
                       " --compact --no-create-info " +
                       "--no-data --routines " + db);
  InputStream in = run.getInputStream();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));

  StringBuilder temp = new StringBuilder();

  String buffer;

  while ((buffer = br.readLine()) != null) {
            temp.append(buffer).append("\n");
      }

  br.close();
  in.close();

  return temp.toString();
 }

    public MysqlBackup(String host, String port, String user,
                           String password, String db) {
        this.host=host;
        this.port=port;
        this.user=user;
        this.password=password;
        this.db=db;
    }

    /**
     * @throws java.lang.Exception
     *
     * Wrapper di getData
     * <strong>
     * LA FUNZIONE NON È OTTIMIZZATA E ALLOCA MOLTA RAM <BR>
     * SERVE SOLO PER FARE TEST
     * </strong>
     */
    public String data_to_string() throws Exception{
        return getData(host, port, user, password, db);
    }

    /**
     *
     * Wrapper di getRoutine()
     * @throws java.lang.Exception
     */
    public String routine_to_string() throws Exception{
        return getRoutine(host, port, user, password, db);
    }

    /**
     *
     * @param nomefile
     * @return true se va bene, false altrimenti
     * Scrive i dati su un file, funzione ottimizzata per allocare meno ram
     */
    public boolean data_to_file(String nomefile) {
        File filedst = new File(nomefile);
        try {
            FileOutputStream dest = new FileOutputStream(filedst);
            getData(host, port, user, password, db, dest);
            dest.flush();
            dest.close();
        } catch (Exception ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }

    /**
     *
     * @param nomefile
     * @return true se va bene, false altrimenti
     * Scrive i dati su un file
     */
    public boolean routine_to_file(String nomefile){
        File filedst = new File(nomefile);
        try {
            FileOutputStream dest = new FileOutputStream(filedst);
            dest.write(routine_to_string().getBytes());
            dest.flush();
            dest.close();
        } catch (Exception ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }

    /**
     *
     * @param nomefile
     * @return true se va bene, false altrimenti
     * genera un file zip con all'interno due files: <br>
     * data.sql con i dati <br>
     * routine.sql con la struttura e le procedure
     */

    public boolean all_to_zip(String nomefile){
        try {
            File filedst = new File(nomefile);
            FileOutputStream dest = new FileOutputStream(filedst);
            ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(dest));
            zip.setMethod(ZipOutputStream.DEFLATED);
            zip.setLevel(Deflater.BEST_COMPRESSION);
            zip.putNextEntry(new ZipEntry("data.sql"));
            getData(host, port, user, password, db, zip);
            zip.putNextEntry(new ZipEntry("routine.sql"));
            zip.write(routine_to_string().getBytes());
            zip.close();
            dest.close();
        } catch (Exception ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }
}

Share Button

5 comments

Vai al modulo dei commenti

  1. Antonio

    Ciao Vincenzo, sto provando ad utilizzare la tua classe, ma avendo un Mac non riesco a trovare il programma mysqldump.exe hai idea di come posso aggirare la cosa?

  2. Vincenzo La Spesa

    mmm, non ho mai toccato un Mac per più di 10 minuti di fila… provo a chiedere ai miei contatti xD

  3. Vincenzo La Spesa

    Dunque, intanto non devi cercare mysqldump.exe ma semplicemente mysqldump, se lo chiami da terminale lo trova? o non l’hai proprio installato? se è installato basta un which mysqldump per sapere dove si trova

  4. Remo

    Scusami ma c’è una classe che fa anche il ripristino da file dump.zip ?

  5. Vincenzo La Spesa

    non so.
    purtroppo il mio codice però non lo fa, l’ho sviluppato per fare backup periodici nella speranza che non servissero mai xD

Commenti disabilitati.