Synchronisation de 2 BDD MySQL en PHP

Fermé
Signaler
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020
-
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020
-
Bonjour, j'ai besoin d'exporter ma base de données MySQL fonctionnant sur un Serveur Local Windows Server 2012 R2, l'export devrait se faire vers un Serveur En Ligne hébergé chez IONOS et pour laquelle la base de données possède la même structure que celle En Local mais de nom différent. Comment m'y prendre ?

Dans la seconde étape, il sera question que j'écrive un autre script PHP sur le Serveur IONOS à distance qui tourne sur LINUX, lequel script PHP va se charger d'importer ce fichier exporté depuis mon Serveur Local Windows Server ... Alors, ma question : Comment m'y prendre pour Réussir le tout ?

6 réponses

Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021
3 852
Bonjour,

Pour des bases mysql ... il suffit de faire un DUMP de celle que tu veux sauvegarder, puis importer ce DUMP dans ta nouvelle BDD

https://phoenixnap.com/kb/how-to-backup-restore-a-mysql-database

https://www.sqlshack.com/how-to-backup-and-restore-mysql-databases-using-the-mysqldump-command/

.
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

Je suis tout à fait d'accord avec Vous sur ce point (c'est-à-dire "En Ligne de Commande"), seulement que dans mon cas le problème c'est d'écrire un script PHP qui devrait faire d'abord l'EXPORT de toute ma Base De Données en Local, puis se connecter au Serveur En Ligne MySQL de IONOS pour faire le sens contraire, c'est-à-dire l'IMPORT de ladite Base MySQL qui a la même structure ... Comment écrire ce script PHP ??? Parce que je ne suis pas certain que la syntaxe du Code qui fonctionne En Ligne de Commande est la même que celle à écrire dans un script PHP !!! C'est 2 environnements totalement différent. En plus, ce script doit être automatisé, je devrais créer une tâche CRON sur mon Windows Server pour qu'il le fasse automatiquement, bien sûr à des intervalles réguliers, genre toutes les 3 heures du temps (à 6h30, puis à 9h30, puis encore à 12h30, 15h30, 18h30, 20h30 et il devrait s'arrêter à 23h30 par exemple ...).
Voilà c'est exactement en détails de çà qu'il s'agit en définitive.
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021
3 852

puis se connecter au Serveur En Ligne MySQL de IONOS

Déjà .. ce point la risque de bloquer....

L'accès à distance de ta BDD ( sur un serveur IONOS) est, le plus souvent impossible.



C'est 2 environnements totalement différent. En plus, ce script doit être automatisé, je devrais créer une tâche CRON sur mon Windows Server pour qu'il le fasse automatiquement, bien sûr à des intervalles réguliers, genre toutes les 3 heures du temps (à 6h30, puis à 9h30, puis encore à 12h30, 15h30, 18h30, 20h30 et il devrait s'arrêter à 23h30 par exemple ...).

Via cette Tache CRON, génère un DUMP de ta BDD ..puis envois en FTP, le DUMP sur ton server IONOS
Puis, sur ton serveur IONOS, faire également une tache CRON qui chargerait ce DUMP dans ta bdd.
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

Jai l'envie de dire que la syntaxe de mysqldump n'est adaptée qu'ene ligne de commande et non dans un script PHP, car voilà que j'ai mis ce script puis paramétré une tâche planifiée sous Windows Server 2012 R2 (tâche CRON) et en allant dans le système, le Planificateur de tâches Windows m'indique un message : "L'opération a été annulée par l'utilisateur. (0x800704C7) ...
Voici ce qua été le contenu de mon script PHP que j'ai logé dans un dossier de mon application :
//Entrez ici les informations de votre base de données et le nom du fichier de sauvegarde.
$mysqlDatabaseName ='database';
$mysqlUserName ='xxxxxxxxxxxxxx';
$mysqlPassword ='xxxxxxxxxxxxxx';
$mysqlHostName ='adresse ip';
$mysqlExportPath ='fichier-export.sql';

//Veuillez ne pas modifier les points suivants
//Exportation de la base de données et résultat
$command='mysqldump --opt -h' .$mysqlHostName .' -u' .$mysqlUserName .' -p' .$mysqlPassword .' ' .$mysqlDatabaseName .' > ' .$mysqlExportPath;
exec($command,$output=array(),$worked);
switch($worked){
case 0:
echo 'La base de données <b>' .$mysqlDatabaseName .'</b> a été stockée avec succès dans le chemin suivant '.getcwd().'/' .$mysqlExportPath .'</b>';
break;
case 1:
echo 'Une erreur s est produite lors de l exportation de <b>' .$mysqlDatabaseName .'</b> vers'.getcwd().'/' .$mysqlExportPath .'</b>';
break;
case 2:
echo 'Une erreur d exportation s est produite, veuillez vérifier les informations suivantes : <br/><br/><table><tr><td>MySQL Database Name:</td><td><b>' .$mysqlDatabaseName .'</b></td></tr><tr><td>MySQL User Name:</td><td><b>' .$mysqlUserName .'</b></td></tr><tr><td>MySQL Password:</td><td><b>NOTSHOWN</b></td></tr><tr><td>MySQL Host Name:</td><td><b>' .$mysqlHostName .'</b></td></tr></table>';
break;
}


Je ne vois pas dans mon Code là où le bas blaisse ...
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021
3 852
Vu le message d'erreur, il s'agit d'avantage d'un pb d'exécution du script depuis la planificateur de tâches.
Est-ce que au moins, tu as testé le script directement.... (sans passer par le planificateur ) ?
Et puis, comment as tu créés ta tâche planifiée ?
Avec quel user as tu programmé cette tâche ?
En général, on exécute le script PHP depuis un fichier bat .. et c'est ce bat qui est lancé par windows... et il faut que le PATH vers l'exe de PHP soit configuré dans le système
(mais là, on sort du cadre de ce forum qui ne traite que du langage php... si tu as des soucis pour planifier la tâche, faudra certainement poser une question dans le forum windows.)

A noter que tu pourrais aussi générer ton dump en powershell ...
par exemple
https://gallery.technet.microsoft.com/scriptcenter/PowerShell-to-perform-a687f0df
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020
>
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021

En suivant votre Lien-ci https://gallery.technet.microsoft.com/scriptcenter/PowerShell-to-perform-a687f0df, je n'ai pas vu Comment ils expliquent la génération du DUMP en PowerShell ...
Pour répondre à vos questions, je dirai :
1/- Comment vais-je tester le script directement sans passer par le planificateur ?
2/- Pour la création de ma tâche planifiée, j'ai tout simplement suivi ce tuto via ce Lien-ci https://www.pcastuces.com/pratique/astuces/4245.htm
3/- De quel User faites-vous allusion ? J'ai mis en début de mon Script PHP le Nom de l'Utilisateur que j'avais créé dans phpMyAdmin, ainsi que son Mot De Passe, comme ceci :
$mysqlDatabaseName ='nom de la base de données';
$mysqlUserName ='nom de l'utilisateur de la base de données';
$mysqlPassword ='mot de de l'utilisateur de la base de données';
$mysqlHostName ='adresse ip du serveur';
$mysqlExportPath ='fichier-export.sql';


4/- Comment on exécute un script PHP depuis un fichier bat ?
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021
3 852 >
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

Comment, fais-tu, pour exécuter un script PHP en ligne de commande ?
si tu es capable de répondre à cette question, alors tu sais comment faire depuis un fichier BAT....
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

En revanche, toujours dans ma quête de solutions, j'avais trouvé un Script sur GitHub, lequel vous fait l'Export d'une Base de données via PHP et la sauvegarde via FTP, mais je ne l'ai pas encore essayé. Voici intégralement le Script PHP organisé sous forme de 2 fichiers :

A/ - Script PHP n° 1 :
/**
* DatabaseExport is a tool to export database via PHP and store it via FTP
*
* Copyright (c) 2011 Tomas Pavlatka (http://tomas.pavlatka.cz)
*
* @package DatabaseExport
*/

header("content-type: text/plain; charset=utf-8");

// Require classes.
require_once 'classes/Database.php';

// Export params.
$params = array(
    'database' => array(
	    'db_host'       => 'localhost',
	    'db_name'       => 'db_name',
	    'db_user'       => 'root',
	    'db_password'   => '',
	    'db_charset'    => 'utf8'),
    'ftp' => array(
        'ftp_server'    => '',
        'ftp_username'  => '',
        'ftp_password'  => '',
        'ftp_folder'    => ''
    ),
    'export' => array(
        'export_folder' => './backups/',
        'export_zip'    => 'bzip2',
    )
);

// Export database..
$dbObj = new PTX_Database($params['database']);
$dbObj->connect();

$dbTables = array();
if($dbObj->mysqlListTables()) {
	while($table = $dbObj->mysqlFetchArray()){
		$dbTables[] = (string)$table[0];	
	}
}
$exportedData = $dbObj->dbExport($dbTables);
	
// Save a file.
$fileName = $params['database']['db_name'].'-'.date('YmdHis').'.sql';
$filePath = $params['export']['export_folder'].$fileName;

if($params['export']['export_zip'] == 'bzip2') {
    $fileName .= '.bz2';
    $filePath .= '.bz2';
	$bz = bzopen($filePath, "w");
    bzwrite($bz, $exportedData);
    bzclose($bz);
} else {
	$fopen = fopen($filePath,'w+');
	fwrite($fopen,$exportedData);
	fclose($fopen);	
}

// Copy to FTP.
$ftpConnect = ftp_connect($params['ftp']['ftp_server']);
$ftpLogin = ftp_login($ftpConnect, $params['ftp']['ftp_username'], $params['ftp']['ftp_password']);
if($ftpLogin) {
    // Upload a file
    $destination = $params['ftp']['ftp_folder'].$fileName;
    $upload = ftp_put($ftpConnect, $destination, $filePath, FTP_BINARY); 	
}
ftp_close($ftpConnect); 


B/ - Script PHP n° 2 :
/**
* DatabaseExport is a tool to export database via PHP and store it via FTP
*
* Copyright (c) 2011 Tomas Pavlatka (http://tomas.pavlatka.cz)
*
* @package DatabaseExport
*/

class PTX_Database {
	
	/*
	 * Holds actual connection.
	 */
	private $_dbConnect;
	
    /*
     * Private variable holding option for class.
     */
	private $_options = array(
		'db_host'       => '',
	    'db_name'       => '',
	    'db_user'       => '',
	    'db_password'   => '',
	    'db_charset'    => 'utf-8');

	private $_selectQuery;
	
	/**
	 * Construct.
	 * 
	 * constructor of the class
	 * @param array $options - parameters for class
	 */
	public function __construct(array $options = array()) {
		$this->_options = array_merge($this->_options,$options);
	}
	
	/**
	 * Connect.
	 * 
	 * connects to the database.
	 */
	public function connect(){
       
		if(!$this->_dbConnect = @mysql_connect($this->_options['db_host'],$this->_options['db_user'],$this->_options['db_password'])){
            exit('Unable to connect to database');
        }
        if(!@mysql_select_db($this->_options['db_name'], $this->_dbConnect)) {
            exit(sprintf('Unable to connect to database %s',$this->_options['db_name']));
        }
        
        // Set charset.
        mysql_query("SET CHARACTER SET ".$this->_options['db_charset']);
	}
	
	/**
	 * Export.
	 * 
	 * exports database into text
	 * @param array $tables - list of the table
	 * @return exported data
	 */
    public function dbExport(array $tables) {
        $exportData = null;
        
    	foreach($tables as $table) {
            $exportData .= $this->_createExportHeader($table);
            $exportData .= $this->_getExportData($table);
        }
        
        return $exportData;
    }
    
    /**
     * Mysql Fetch Array.
     * 
     * fetch array from database.
     */
    public function mysqlFetchArray(){
        return @mysql_fetch_array($this->_selectQuery);
    }
    
    /**
     * Mysql Fetch Assoc.
     * 
     * fetch array assoc from database.
     */
    public function mysqlFetchAssoc(){
        return @mysql_fetch_assoc($this->_selectQuery);
    }
	
    /**
     * Mysql List Tables.
     * 
     * mysql_query to find all tables in database.
     * @return true | false
     */
    public function mysqlListTables(){
        if(!$this->_selectQuery = @mysql_query("SHOW TABLES FROM ".$this->_options['db_name'],$this->_dbConnect)) {
            return false;
        } else {
            return true;	
        }
    }
    
    /**
     * Create export header (Private).
     * 
     * creates header for export
     * @param $table - name of a table
     * @return header
     */
    private function _createExportHeader($table) {
    	// Fields.
    	$fields = array();
    	$query = mysql_query("DESCRIBE `{$table}`",$this->_dbConnect);
        while($field = mysql_fetch_assoc($query)) {
              $fields[] = $field;
        }
        
        // Indexes.
        $indexes = array();
        $query = mysql_query("SHOW INDEXES FROM `{$table}`");
        while($index = mysql_fetch_assoc($query)) {
            if(isset($indexes[$index['Key_name']])) {
            	$indexes[$index['Key_name']][] = $index;
            } else {
            	$indexes[$index['Key_name']] = array($index);
            }
        }
        
        // Table status.
        $query = mysql_query("SHOW TABLE STATUS WHERE `Name` = '{$table}'");
        $status = mysql_fetch_assoc($query);
        
        // Table header.
        $header  = "DROP TABLE IF EXISTS `{$table}`;\n";
        $header .= "CREATE TABLE `{$table}` (\n";
        foreach($fields as $key => $values) {
        	$header .= "\t`".$values['Field']."` ".$values['Type'];
        	if($values['Null'] == 'NO') {
        		$header .= " not null";
        	} else {
        		$header .= " null";
        	}
        	
        	// TODO: What about MySQL constants ?
        	if(!empty($values['Default'])) {
        		if($values['Default'] == 'CURRENT_TIMESTAMP') {
        			$header .= " default ".$values['Default'];
        		} else {
                    $header .= " default '".$values['Default']."'";
        		}
        	}
        	if(!empty($values['Extra'])) {
        		$header .= " ".$values['Extra'];
        	}
        	
        	$header .= ",\n";
        }
        
        $countIndexes = count($indexes);
        $counter = 1;
        foreach($indexes as $indexKey => $indexValeus) {
        	if($indexKey == 'PRIMARY') {
        		$header .= "\tPRIMARY KEY (";
                    $keyString = null;
        		    foreach($indexValeus as $indKey => $indValues) {
                        $keyString .= "`".$indValues['Column_name']."`,";
                    }
                    $header .= substr($keyString,0,-1);
        	} else {
        		$header .= "\tKEY `".$indexKey."` (";
                    $keyString = null;
                    foreach($indexValeus as $indKey => $indValues) {
                    	
                        $keyString .= "`".$indValues['Column_name']."`";
                        
                        if(!empty($indValues['Sub_part'])) {
                        	$keyString .= ' ('.$indValues['Sub_part'].')';
                        }
                        $keyString .= ",";
                    }
                    $header .= substr($keyString,0,-1);
        	}
        	
        	if($counter++ < $countIndexes) {
        		$header .= "),\n";
        	} else {
        		$header .= ")\n";
        	}
        }
        
        $header .= ") ";
        
        // Additional information.
        $charsetExplode = explode('_',$status['Collation']);
        $status['Charset'] = (isset($charsetExplode[0])) ? $charsetExplode[0] : null;
        $additionalInfo = array('Engine' => 'ENGINE','Auto_increment' => 'AUTO_INCREMENT', 'Charset' => 'CHARSET', 'Collation'  => 'COLLATE');
        foreach($additionalInfo as $key => $name) {
        	if(isset($status[$key]) && !empty($status[$key])) {
        		$header .= $name .'='.$status[$key]." ";
        	} 
        }
        $header .= ";\n\n";
        
        return (string)$header;
    }

    /**
     * Get Export Data (Private).
     * 
     * exports records from database.
     * @param $table - name of a table
     * @return export of records
     */
    private function _getExportData($table) {
        $d = null;
        $data = mysql_query("SELECT * FROM `{$table}` WHERE 1", $this->_dbConnect);
        
        $counter = 1;
        $insertData = null;
        $rowCounter = mysql_num_rows($data);
        if($rowCounter > 0) {
	        while($row = mysql_fetch_assoc($data)) {
	        	if($counter == 1) {
	                $insertData .= "INSERT INTO `{$table}` ";
	                    $columns = array_keys($row);
	                    $columnNames = null;
	                    foreach($columns as $key => $column) {
	                    	$columnsNames .= "`{$column}`,";
	                    }
	                $insertData .= "(".substr($columnsNames,0,-1).") VALUES \n";
	            } 
	            
	            $insertData .= "(";
	            $rowData = null;
	            foreach($row as $column => $value) {
	                $rowData .= "'".mysql_escape_string($value)."',";
	            }
	            $insertData .= substr($rowData,0,-1);
	            
	            if($counter < $rowCounter) {
	                $insertData .= "),\n";
	            } else {
	            	$insertData .= ");\n\n";
	            }
	            
	            // Increase counter;
	            $counter++;
	        }
        }
        
        // Return data.
        return (string)$insertData;
    }
}


Contrairement au premier, ce script me paraît beaucoup plus cohérent ... C'est vrai qu'il est un peu plus long... Qu'en dites-vous ?
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

Bonjour, en local comme sur le serveur le DUMP de ma base de données s'exécute bien via un fichier .bat dans une tâche planifiée sous Windows/ Windows Server 2012 R2 ... Pour l'export, je testais une procédure avec SSH qui a bel et bien exporté le fichier sur le serveur IONOS, seulement quand je lance l'import, çà me met ce message Unknown collation: 'utf8mb4_0900_ai_ci'
J'ai essayé de remplacer dans mon fichier sql que j'ai exporté mais toujours Rien, vu le fait que IONOS est sur MariaDB et moi sur MySQL 8.0.17 - MySQL Community Server - GPL

- Autre préoccupation : existerait-il une autre méthide en PHP pour envoyer le DUMP par FTP sur le serveur de IONOS ?
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021
3 852
pour ce qui concerne le message d'erreur, il faut voir si tu peux mettre à jour la version de MariaDB utilisé sur ionos.

et pour ce qui est de faire du FTP en PHP oui, c'est tout à fait possible il existe des fonctions spécifiques pour ça que tu trouveras dans la documentation PHP
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020
>
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021

Donc Vous convenez avec moi que ma vesrion MySQL 8.0.17 - MySQL Community Server - GPL est plus à jour que la version MariaDB de IONOS ? Si Oui, êtes-vous sûr que IONOS permettra qu'on mette à jour sa version de Base de données ? Parce que là il paraîtrait que lorsque je créé ma base de données sur IONOS, il faut que j'indique utf8_general_ci afin qu'il soit compatible avec mon DUMP exporté ...

Voici un peu à quoi ressemble mon fichier .bat qui fait le DUMP :
@echo off
mysqldump -h localhost -u Toto -ppassword maBase > C:\folder\loop.sql

Ainsi que celui qui fait le FTP
ftp -s:C:\folder\gestion_Extranet.ftp
Messages postés
34207
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
1 décembre 2021
3 852 >
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

Voici un peu de lecture pour info :
https://www.ionos.fr/digitalguide/hebergement/aspects-techniques/mariadb-vs-mysql/

Si tu es sur un hébergement mutualisé, je doute que tu puisses upgrader la version de mariadb.

Il faut que rendes la BDD qui se trouve sur ton windows "compatible" avec la version de mariadb présente sur ionos.
ça comment donc par la "collation" des tables à modifier en utf8_general_ci (ou équivalent) tel que tu l'as déjà découvert.
Messages postés
21
Date d'inscription
mardi 16 juin 2020
Statut
Membre
Dernière intervention
2 décembre 2020

Bonsoir, Oui c'est vrai que je ne pourrai pas mettre à jour la version du SGBD de IONOS, par contre la mienne sur mon PC Oui ... J'ai fait plusieurs Tests aujourd'hui en ligne de commande, et effectivement c'est mon encodage qui a créé des problèmes ... Je suis parti d'une base de données vierge que j'ai créé en local puis en ligne en respectant l'encodage UTF-8, l'import manuel a marché ... Mais il se pose un autre problème, celui des droits ... En effet, ma Base en local a un Root dont le mot de passe est "hyper composé" avec des signes + et autres que j'avais mis, ne sachant pas les problèmes que cela devrait me causer ... Du coup, même quand je fais le DUMP avec le Root, çà ne passait pas, j'étais obligé de créer un USER avec tous les GRANT puis le DUMP avait fonctionné ... Maintenant quand j'importe en ligne de commande sur IONOS, çà me met "ERROR 1227 (42000) Access denied", me disant que je n'ai pas assez de privilèges ... Alors que dois-je faire dans ce cas ?