Hilfe bei PHP / Bash / SQL Anwendungen

Localhorst

Keks-Verteiler
Registriert
12 Nov. 2014
Beiträge
1.662
Hallo Leute,

in bin gerade am verzweifeln, da ich seit 10 Stunden an ein Problem sitze und es einfach nicht gelöst bekomme. Folgendes ist der Sachverhalt:

Es geht um Open FOG, ein Projekt bei dem man Computer imagen kann, dieses setzt auf PHP und MySQL. Jetzt haben wir in unserer Firma einen kleinen Sonderfall, bei dem die integrierte Replikation von FOG nicht nutzen können und selber schreiben müssen. Entsprechend gibt es dann auch zwei MySQL Datenbanken, eine bei dem Server der hier steht und eine an dem Ort, wohin Repliziert werden soll. Jetzt stehe ich tatsächlich vor der Aufgabe, wie ich eine Zeile einer Tabelle auf die andere hinmigriere. Folgende Struktur hat die Tabelle:

Code:
Expand Collapse Copy
`imageID` int(11) NOT NULL,
  `imageName` varchar(40) NOT NULL,
  `imageDesc` longtext NOT NULL,
  `imagePath` longtext NOT NULL,
  `imageProtect` mediumint(9) NOT NULL,
  `imageMagnetUri` longtext NOT NULL,
  `imageDateTime` timestamp NOT NULL DEFAULT current_timestamp(),
  `imageCreateBy` varchar(50) NOT NULL,
  `imageBuilding` int(11) NOT NULL,
  `imageSize` varchar(255) NOT NULL,
  `imageTypeID` mediumint(9) NOT NULL,
  `imagePartitionTypeID` mediumint(9) NOT NULL,
  `imageOSID` mediumint(9) NOT NULL,
  `imageFormat` char(1) DEFAULT NULL,
  `imageLastDeploy` datetime NOT NULL,
  `imageCompress` int(11) DEFAULT NULL,
  `imageEnabled` enum('0','1') NOT NULL DEFAULT '1',
  `imageReplicate` enum('0','1') NOT NULL DEFAULT '1',
  `imageServerSize` bigint(20) UNSIGNED NOT NULL DEFAULT 0

und bei der Zieldatenbank ist es genau das selbe. Ich hatte jetzt mehrere Ideen. Als erstes über PHP, da habe ich mir alle werte über
Code:
Expand Collapse Copy
SELECT * FROM `images` WHERE `imageID`=2
in eine Variable geben lassen, fetch_array laufen lassen und wollte dann inserten. Pustekuche, wollte er nicht.

Zweite Idee, über shell_exec lasse ich ein Bash Skript laufen, dass
Code:
Expand Collapse Copy
mysql --user=foga --password=2123135 --database=fog --host=127.0.0.1 --execute="SELECT * FROM `images` WHERE `imageID`=2 INTO OUTFILE '/var/lib/transfer/sql.tmp' FIELDS TERMINATED BY ',';"

ausgibt und dann im nächsten Schritt wieder importiert. Auch das geht nicht, manchmal habe ich falsch gequotet, manchmal falsche Variablen gesetzt. Ich bin am Ende :( Ich habe noch nie PHP gecoded und nach 10 Stunden try and error, wovon 3 Stunden nun auf diese scheiss Datenbank Übertragung draufgingen platzt mir der Kopf und hoffe auf Hilfe von euch :(

Ich kann mir sehr gut vorstellen, dass ich es bereits im PHP Skript hinbekommen würde alle Werte per SELECT in ein Array zu schreiben, und es dann in der zweiten DB ein INSERT / UPDATE zu machen.

Liebe grüße
Stephan
 
Was nutzt du in PHP? ?

Habe es gerade getestet, auf dem gleichen host, sollte aber keinen unterschied machen. Meine Datenbank hat eine Tabelle "items"


Code:
Expand Collapse Copy
aufbau von "items":
id: int(11)
path: text
pattern: text
comment: text
hash: text
lineNumber: varchar(10)
date: date
status: int


[src=php]
// request
// aufbau verbindung
$pdo = new PDO('mysql:host=localhost;dbname=test', 'rootuser', 'rootpass');
// prepare beachte die :id
$statement = $pdo->prepare("SELECT * FROM items WHERE id = :id");
// id muss hier in einem assoc array mitgegeben werden, sonst gibts Fehler (to few statements)
$statement->execute(['id' => 1]);
// hole alle werte die zutreffen
// FETCH_ASSOC um gleich an assoc array zu kriegen und kein object
$q = $statement->fetchAll(PDO::FETCH_ASSOC);


// insert
// verbindung zur entfernten db
$pdo = new PDO('mysql:host=localhost;dbname=test2', 'rootuser', 'rootpass');
// gleiches wie oben, die werte mit : sind wichtig
$statement = $pdo->prepare("INSERT INTO items (id, path, pattern, comment, hash, lineNumber, date, status) VALUES (:id, :path, :pattern, :comment, :hash, :lineNumber, :date, :status)");
// alle daten vom request als parameter mitgeben
// $q[0] weil $statement->fetchAll() ein array zurückgibt, du könntest auch nur $statement->fetch(PDO::FETCH_ASSOC) nutzen, dann brauchst du auch kein [0]
$statement->execute($q[0]);
[/src]
 
  • Thread Starter Thread Starter
  • #3
Ich hab das über mysqli gelöst wenn du das meinst. Kurzer snippet:

[src=php]

$link = mysqli_connect("logalhost", "s3cret", "alsosecret", "db"); //connect Database

if($result2 = $link->query("SELECT `imageID`,`imageName`,`imageDesc`,`imagePath`,`imageProtect`,`imageMagnetUri`,`imageDateTime`,`imageCreateBy`,`imageBuilding`,`imageSize`,`imageTypeID`,`imagePartitionTypeID`,`imageOSID`,`imageFormat`,`imageLastDeploy`,`imageCompress`,`imageEnabled`,`imageReplicate`,`imageServerSize` FROM `images`"))

[/src]

Ich probier das später mit dem PDO aus :)

--- [2019-12-18 16:04 CET] Automatisch zusammengeführter Beitrag ---



Ich habe mal den entsprechend angepasst, AAAAAAAber die endDB bleibt immer noch leer o.O

[src=php]
$imageID=11;
// request
// aufbau verbindung
$pdo = new PDO('mysql:host=localhost;dbname=db1', 'secret', 'secret2');
// prepare beachte die :id
$statement = $pdo->prepare("SELECT * FROM items WHERE id = :imageID");
// id muss hier in einem assoc array mitgegeben werden, sonst gibts Fehler (to few statements)
$statement->execute(['id' => $imageID]);
// hole alle werte die zutreffen
// FETCH_ASSOC um gleich an assoc array zu kriegen und kein object
$q = $statement->fetchAll(PDO::FETCH_ASSOC);

// insert
// verbindung zur entfernten db
$pdo = new PDO('mysql:host=remotehost;dbname=db_dev', 'secret', 'D4kNVRkFlEbqaE1r');
// gleiches wie oben, die werte mit : sind wichtig
$statement = $pdo->prepare("INSERT INTO items (imageID, imageName, imageDesc, imagePath, imageProtect, imageMagnetUri, imageDateTime, imageCreateBy, imageBuilding, imageSize, imageTypeID, imagePartitionTypeID, imageOSID, imageFormat, imageLastDeploy, imageCompress, imageEnabled, imageReplicate, imageServerSize) VALUES (:imageID, :imageName, :imageDesc, :imagePath, :imageProtect, :imageMagnetUri, :imageDateTime, :imageCreateBy, :imageBuilding, :imageSize, :imageTypeID, :imagePartitionTypeID, :imageOSID, :imageFormat, :imageLastDeploy, :imageCompress, :imageEnabled, :imageReplicate, :imageServerSize)");
// alle daten vom request als parameter mitgeben
// $q[0] weil $statement->fetchAll() ein array zurückgibt, du könntest auch nur $statement->fetch(PDO::FETCH_ASSOC) nutzen, dann brauchst du auch kein [0]
$statement->execute($q[0]);

[/src]

Wie gesagt, das ende bleibt leer :confused: Any Idea wie ich nun debugge?
 
Zuletzt bearbeitet:
was gibt dir denn das aus? Damit solltest du den gesamten Datensatz deiner Quelldb bekommen.

[src=php]
$imageID=11;
$pdo = new PDO('mysql:host=localhost;dbname=db1', 'secret', 'secret2');
$statement = $pdo->prepare("SELECT * FROM items WHERE id = :imageID");
$statement->execute(['id' => $imageID]);
$q = $statement->fetchAll(PDO::FETCH_ASSOC);
var_dump($q);
[/src]

Kleiner Umbau, zum testen der Verbindung, betrifft beide "connects"

[src=php]
// quelle
$pdo = new PDO('mysql:host=localhost;dbname=db1', 'secret', 'secret2');
$statement = $pdo->prepare("SELECT * FROM items WHERE id = :imageID");
if(!$statement) {
echo 'PDO ERROR <br>';
print_r($pdo->errorInfo());
}
// select wie oben
$pdo = new PDO('mysql:host=remotehost;dbname=db_dev', 'secret', 'D4kNVRkFlEbqaE1r');
$statement = $pdo->prepare("INSERT INTO items (imageID, imageName, imageDesc, imagePath, imageProtect, imageMagnetUri, imageDateTime, imageCreateBy, imageBuilding, imageSize, imageTypeID, imagePartitionTypeID, imageOSID, imageFormat, imageLastDeploy, imageCompress, imageEnabled, imageReplicate, imageServerSize) VALUES (:imageID, :imageName, :imageDesc, :imagePath, :imageProtect, :imageMagnetUri, :imageDateTime, :imageCreateBy, :imageBuilding, :imageSize, :imageTypeID, :imagePartitionTypeID, :imageOSID, :imageFormat, :imageLastDeploy, :imageCompress, :imageEnabled, :imageReplicate, :imageServerSize)");
if(!$statement) {
echo 'PDO ERROR <br>';
print_r($pdo->errorInfo());
}
// inserten wie oben
[/src]
 
  • Thread Starter Thread Starter
  • #5
Danke dir vielmals! Also ich den ersten Umbau gemacht habe mit var_dump hab ich gesehen, das Array war leer. Und dann viel es mir wie Schuppen von den augen. Ich hatte den falschen Tabellennamen angegeben :uglyngb: Da kann es natürlich nichts werden :uglyngb:

Danke die viel vielmals! Dann wäre mein komplettes Skript bald fertig. Muss dann nur noch ein paar Update Querys einbauen, aber dann läufts. Nochmal, vielen vielen Dank!!!
 
Und dann viel es mir wie Schuppen von den augen. Ich hatte den falschen Tabellennamen angegeben :uglyngb: Da kann es natürlich nichts werden :uglyngb:
Sowas hab ich mir fast gedacht, deshalb hab ich auch gleich mal den var_dump mit angehängt. ;) Mit PDO lässt es sich deutlich angenehmer arbeiten als mit mysqli, ein paar updatequeries sind da relativ einfach gemacht.
 
  • Thread Starter Thread Starter
  • #8
Hey Doc,

danke dir für den Tipp. Jedoch wird das in diesem Fall leider nicht zu 100% passen, da auf den anderen Nodes die Informationen doch leicht abweichen werden. Nachdem ich nun die Grundstruktur meines Codes habe fiel mir auf das es nicht zu 100% passt, weil ich eben auch die imageID mitgebe. Ist eben schon lange her gewesen das ich mir SQL gearbeitet habe. Den Code werde ich dann die nächsten Tage entsprechend umschreiben. Ich weiß in der Struktur welches der Index ist. Ansonsten zerschiesse ich mir glaube ich etwas mit dem Auto Increment falls sich das Anwendungsgebiet doch mal ändert. Es war bei mir eben eine Hürde wieder mit PHP anzufangen und ich hatte immer schon Probleme Daten in eine Datenbank zu schreiben. Aber mir der Hilfestellung von habe jetzt einen weg über PDO dann die Daten doch hineinzuschreiben. Entsprechend muss ich dann schauen wie ich einen if Schalter baue, der dann anstatt eines INSERT ein UPDATE macht. Wird mich noch einige Tage kosten, aber momentan macht das Projekt wirklich Spaß und ist das erste mal das es auch wirklich gebraucht wird :)
 
Wenn sich der Inhalt ändern soll sind sonst "Trigger" noch eine Option das ganze trotzdem innerhalb der Datenbank zu regeln.
Wobei ich mir da gerade auch nicht sicher bin ob mysql / Mariadb das über 2 DB-Server hinweg hin bekommt (zur not müsste man über eine zwischentabelle gehen und diese dann replizieren).
Da du schon fast fertig bist nicht mehr so wichtig - nur falls es mal "flotter" oder mit weniger Ressourcen laufen soll - weiß ja nicht wie viel sich in der Tabelle so ändert :)
 
Entsprechend muss ich dann schauen wie ich einen if Schalter baue, der dann anstatt eines INSERT ein UPDATE macht.

Idee1: mach eine Anfrage an die Zieldatenbank, wenn der Eintrag dort existiert, dann update, ist er nicht da, dann Insert. - relativ Aufwändig und braucht auch mehr resourcen
Idee2: erstell in der source Datenbank eine extra zelle, in der du speicherst ob die Daten schon portiert wurden, prüfe diesen beim holen - erfordert eingriff in die Source DB, könnte aber leichter nutzbar sein.
 
  • Thread Starter Thread Starter
  • #11
Danke, ich bin aber gerade einfach nen anderen Weg gegangen :D Ich weiß das ImageName nur einmal existieren darf. Also habe ich ein Delete Query gebaut der den Namen löscht. Habs mir halt dadurch einfach gemacht, aber so what :D Habs getestet, es läuft und bin mega mega happy :D
 
Wenn ImageName sowieso eindeutig ist, dann lösch die Spalte ImageID und verwende ImageName als Primary Key.
 
  • Thread Starter Thread Starter
  • #13
Das ist ja das bescheuerte ... sowohl ImageName und ImageID sind eindeutig, weil eine andere Tabelle auf ImageID verweist, das kam wiederrum von dem Software entwickler ^^
 
Zurück
Oben