[MySQL] Efficient 2 tabellen uit 2 databases synchroniseren

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Ik heb een simpel PHP-scriptje gemaakt, waarmee ik de namen van spelers uit tabel spelers van database 1 wil synchroniseren / kopiëren naar de spelers tabel van database 2.

Op zich heb ik dit nu werkend, maar dit is een inefficiënte manier; ik doorloop de spelers tabel van database 1 en maak vervolgens een insert query voor de spelers tabel in database 2. Doordat ik beide spelerstabellen het veld waar de naam staat een unieke eigenschap heb gegeven (om er zeker van te zijn dat de velden uniek zijn) weet ik in ieder geval 100% zeker dat een naam maar 1x voor kan komen in beide tabellen.

So far so good, maar dit kan mijns inziens beter en ik vroeg mij af hoe. Ik heb niet zo heel veel kennis van MySQL en ik heb ook al wel het een en ander gezocht op internet. In mijn zoektocht vond ik dan voornamelijk het synchroniseren van databases, iets wat voor mij niet van toepassing is. Toen ik verder keek kwam ik wel iets tegen met IF (NOT) EXISTS, maar dat is alleen in de SQL query en dus alleen in de database / tabel waar je de query op loslaat. Ik zou dus eigenlijk iets moeten hebben als PL/SQL, zoals dat is met (iig) Oracle, maar ik gebruik (helaas?) MySQL, omdat beide pakketten dit nou eenmaal vragen.

Voor de zekerheid de code die ik nu hiervoor gebruik:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
?php
$host = 'localhost'; // Server
$user = 'usert';      // Gebruikersnaam
$pass = 'pass';  // Wachtwoord

$conn = mysql_connect($host, $user, $pass);

if(!$conn) // Maak connectie met database en controleer of gegevens goed zijn
{
    echo 'Het maken van de verbinding was niet goed. ';
}
else // Selecteer de benodigde database
{
    $seldb = mysql_select_db('ProConStatsLog');
    if(!$seldb) // Controleer of het selecteren van de database gelukt is.
    {
        echo 'Het selecteren van de eerste database is niet gelukt.';
    }
    else // We kunnen een query loslaten
    {
        $query  = "SELECT `SoldierName` FROM `tbl_playerdata`";
        $result = mysql_query($query);
        
        if(!$result) // Controleer of de query uitvoerbaar was
        {
            echo 'Er ging iets mis met het draaien van de query.';
        }
        else // Vang de resultset op
        {
            while($row = mysql_fetch_assoc($result))
            {
                $seldb2 = mysql_select_db('ezstats', $conn);
                if(!$seldb2) // Controleer of verbinden met tweede database is gelukt
                {
                    echo 'Verbinden met tweede database is niet gelukt.';
                }
                else // Zo ja, dan gaan we weer door.
                {
                    $player = mysql_real_escape_string($row['SoldierName']); // Escape de spelernamen waar noodzakelijk
                    $query2  = "INSERT INTO ezstats_players (name) VALUES ('". $player ."');";
                    $result2 = mysql_query($query2);
                    
                    if(!$result2)
                    {
                        echo 'Het invoeren van '. htmlspecialchars($row['SoldierName']) .' is niet gelukt, waarschijnlijk al in de tabel.<br>';
                        echo "\n\r";
                    }
                    else
                    {
                        echo 'Speler '. htmlspecialchars($player) .' is succesvol aan de EZStats toegevoegd<br>';
                    }
                }
            }
        }
    }
}
mysql_close($conn);
?>
En ja, ik weet dat PHP automatisch de verbinding sluit met MySQL, maar wil het liever 100% zeker weten. Zoals te zien is, laat ik door elke resultaat van de eerste query een INSERT query los op de tweede tabel en database, nu weet ik ook wel, dat dit met 1 INSERT query kan, maar dat maakt mijns inziens voor de load niet uit.

Bijkomend is ook nog eens, dat er steeds meer spelers juist erbij komen, waardoor de resultaten van de SELECT alleen maar toenemen. Nu kan ik dat wel weer afvangen met een LIMIT natuurlijk, door steeds om de 100 spelers de limiet te verhogen, maar zoals je begrijpt wil ik niet aan de gang blijven met het bijwerken van het script. Iemand die weet wat ik (door mijn gemis aan de juiste kennis en ervaring) uit de brand kan en wil helpen? :)

Wellicht ten overvloede: de MySQL en PHP draaien op een Debian Testing met de PHP5 en MySQL5 uit diens repositories (exacte versies weet ik even niet).

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Om hoeveel users gaat het?

Had je http://www.maatkit.org/doc/mk-table-sync.html gezien?

Pagineren met limit is dom, en bij 100 users ook zeker niet nodig. Zie http://www.mysqlperforman...imize-paginated-displays/ hoe het wel moet, maar de vraag is hoevaak dit script draait en of er wel een probleem is.
En ja, ik weet dat PHP automatisch de verbinding sluit met MySQL, maar wil het liever 100% zeker weten
Bij dezen.

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Momenteel gaat het nog niet om veel gebruikers (het gaat om spelers die een Bad Company 2 server joinen waarvan ik graag de stats wil bijhouden, zowel lokaal van de server zelf, als de globale), maar dit zal mettertijd wel toenemen. Gametracker.com houdt het ook bij en zit inmiddels aan de 1400 (unieke) spelers en momenteel heb ik iets van rond de 150 spelers in de tabel staan. Dit script is dus puur een zogenaamde 'bridge' om de namen van de spelers van de statistieken van de 'lokale' server over te hevelen naar de 'globale' statistieken, zodat ook die inzichtelijk(er) worden.

Met LIMIT wilde ik dan de de eerste X-honderd gebruikers steeds uitsluiten, zodat die dus steeds overgeslagen worden, wat dus mijn query ten goede komt.

Ik heb net ook even gekeken naar MK-Table-Sync gekeken, die eerste link die je gaf, maar dat is volgens mij binnen een en dezelfde database, waarbij ik het wil synchroniseren naar de spelers tabel in een andere database.

[ Voor 22% gewijzigd door CH4OS op 01-01-2011 13:39 ]


Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 06:35
Misschien een idee om wijzigingen (verwijderde, toegevoegde, aangepaste data) van spelers bij te houden in een andere tabel en bij het 'synchroniseren' de wijzigingen toe te passen op die andere tabel.

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Jaap-Jan schreef op zaterdag 01 januari 2011 @ 13:42:
Misschien een idee om wijzigingen (verwijderde, toegevoegde, aangepaste data) van spelers bij te houden in een andere tabel en bij het 'synchroniseren' de wijzigingen toe te passen op die andere tabel.
Ja, daar zat ik ook al aan te denken, zo'n tussentabel eigenlijk. Alleen leverd mij dat dan toch weer 2 extra queries op? Ik moet dan eerst van A naar B en vervolgens weer van B naar C. Hierdoor lijkt B mij anders aardig overbodig. Er zal overigens alléén (geautomatiseerd) toegevoegd worden.

Acties:
  • 0 Henk 'm!

  • Light
  • Registratie: Augustus 2000
  • Niet online
CptChaos schreef op zaterdag 01 januari 2011 @ 13:35:
Dit script is dus puur een zogenaamde 'bridge' om de namen van de spelers van de statistieken van de 'lokale' server over te hevelen naar de 'globale' statistieken, zodat ook die inzichtelijk(er) worden.
Heb je in de tabel ezstats_players alleen die namen staan, of staat er meer informatie bij?
Ik heb net ook even gekeken naar MK-Table-Sync gekeken, die eerste link die je gaf, maar dat is volgens mij binnen een en dezelfde database, waarbij ik het wil synchroniseren naar de spelers tabel in een andere database.
MK-Table-Sync is volgens mij tussen verschillende servers, terwijl jij verschillende tabellen op dezelfde server wilt gebruiken. Klopt dat laatste?

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Light schreef op zaterdag 01 januari 2011 @ 13:52:
Heb je in de tabel ezstats_players alleen die namen staan, of staat er meer informatie bij?
Daar staat een (uniek) ID, een webID (weet niet waar dit dienst voor doet) en een naampje. :)
MK-Table-Sync is volgens mij tussen verschillende servers, terwijl jij verschillende tabellen op dezelfde server wilt gebruiken. Klopt dat laatste?
Omdat het twee verschillende pakketten zijn, heten de tabellen anders, maar de inhoud is overeenkomend (die spelersnamen). De databases staan dus lokaal wél op dezelfde server.

[ Voor 9% gewijzigd door CH4OS op 01-01-2011 14:21 ]


Acties:
  • 0 Henk 'm!

  • Light
  • Registratie: Augustus 2000
  • Niet online
Een id is niet zo spannend. Maar als het twee tabellen op dezelfde server zijn die ook door dezelfde user kunnen worden benaderd, dan heb je volgens mij helemaal niet zo'n ingewikkeld script nodig.

SQL:
1
INSERT INTO ezstats.ezstats_players (name) SELECT SoldierName FROM ProConStatsLog.tbl_playerdata

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Light schreef op zaterdag 01 januari 2011 @ 14:06:
Een id is niet zo spannend. Maar als het twee tabellen op dezelfde server zijn die ook door dezelfde user kunnen worden benaderd, dan heb je volgens mij helemaal niet zo'n ingewikkeld script nodig.

SQL:
1
INSERT INTO ezstats.ezstats_players (name) SELECT SoldierName FROM ProConStatsLog.tbl_playerdata
Dat vergemakkelijkt het overzetten inderdaad, maar stel, ik heb strakjes 1500 spelers in de tabel ProConStatsLog.tbl_playerdata staan, dan wil hij élke keer al die 1500 spelersnamen overzetten. Doordat ik er al een unique eigenschap heb gegeven aan beide velden in beide tabellen, zijn dat misschien 1450 insert's die niet hoeven. Naar mate er meer en meer spelers in de tabel komen te staan, is de server dus méér daarmee bezig dan wat ie wérkelijk moet doen: alleen de nieuwe spelers toevoegen.

Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 06:35
Nou nee: [quote=http://dev.mysql.com/doc/refman/5.5/en/insert-select.html]• Specify IGNORE to ignore rows that would cause duplicate-key violations.

Oftewel: INSERT IGNORE INTO ... zorgt ervoor dat die gewoon worden overgeslagen.

Kan die data ook wijzigen? Zo ja, dan heb je 'ON DUPLICATE KEY UPDATE' nodig.

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Jaap-Jan schreef op zaterdag 01 januari 2011 @ 14:35:
Nou nee:
Oftewel: INSERT IGNORE INTO ... zorgt ervoor dat die gewoon worden overgeslagen.

Kan die data ook wijzigen? Zo ja, dan heb je 'ON DUPLICATE KEY UPDATE' nodig.
Nee, die data wijzigt niet; begrijp ik het trouwens goed dat de query dan
SQL:
1
INSERT IGNORE INTO ezstats.ezstats_players (name) SELECT SoldierName FROM ProConStatsLog.tbl_playerdata
wordt?

Mocht het zo zijn dat iemand met een andere character op de server komt, heeft die 'soldaat' / speler altijd een andere nickname.

[ Voor 12% gewijzigd door CH4OS op 01-01-2011 16:57 ]


Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Als beide tabellen op dezelfde server staan, waarom gebruik je dan geen VIEW?

SQL:
1
CREATE VIEW ezstats.ezstats_players AS SELECT id, SoldierName as name, 0 as webID from ProConStatsLog.tbl_playerdata


Even hackend vanuit de ezstats-code die ik kon vinden; de originele database ken ik uiteraard niet...

Nadeel is natuurlijk wel dat je de al bestaande informatie in ezstats niet meer kunt gebruiken omdat de IDs veranderd zijn.

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Euh... Is het héél erg dat ik jou niet volg? * CH4OS googled...

Op zich zou een view een mooie oplossing zijn, echter wil ik niet klooien, zodat de software zelf niet werkt.
Ik wil het dus gewoon lekker simpel houden: inlezen van de ene database.tabel en wegschrijven in database2.tabel. Daarmee weet ik zeker dat het werkt, zie het script hierboven, maar dit moet beter en efficiënter kunnen.

Die database van ezStats is niet echt genormaliseerd heb ik het idee, ik heb handmatig die spelersnamen uniek moeten maken, waardoor het enigszins werkbaar is, of althans beter dan wat het standaard is. Met een view erbij denk ik dat ik er teveel stuk aan maak dan mij lief is. Het enige wat ik (voor nu) wil weten is of
SQL:
1
2
    
INSERT IGNORE INTO ezstats.ezstats_players (name) SELECT SoldierName FROM ProConStatsLog.tbl_playerdata
dan de juiste insert query is, dan is het al zoveel efficiënter dan wat het nu is en hoef ik er geen extra dingen tussen te hangen, wat misschien mooier is, maar ik vervolgens nog meer programmeer werk heb om het weer werkend te krijgen.

EDIT: Ik heb de query van hierboven geprobeerd, maar ondanks dat ik géén foutmelding krijg, word de tabel niet bijgewerkt.

[ Voor 51% gewijzigd door CH4OS op 01-01-2011 20:13 ]


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Je krijgt geen foutmelding omdat je ignore doet.

Het slaat ook helemaal nergens op om dit in 1 query te willen proppen. Je kan ook totaal geen bewerkingen meer uitvoeren op de data, mocht je dat (later) nodig vinden.

Je code is ook onnodig complex gemaakt door ifje in ifje in ifje te gebruiken. Ik neem aan dat je dit via de CLI of een Cronjob aanroept? Anders moet je set_time_limit(0); en ignore_user_abort(true); toevoegen. Het is overigens niet aan te raden dit soort scripts via de browser te doen.

Om even een voorbeeld te geven dat de code overzichtelijker is zonder die 100000 tabs:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<?php 
$host = 'localhost'; // Server 
$user = 'usert';      // Gebruikersnaam 
$pass = 'pass';  // Wachtwoord 

$conn = mysql_connect($host, $user, $pass); 
if(!$conn) // Maak connectie met database en controleer of gegevens goed zijn 
{ 
    echo 'Het maken van de verbinding was niet goed.'.PHP_EOL; // Newline :)
    exit(1); // Exit met een foutcode, geen onnodige else waardoor alles 1000 tabs naar rechts staat
}

// Selecteer de benodigde database 
if(!mysql_select_db('ProConStatsLog', $conn)) // Controleer of het selecteren van de database gelukt is. + connectie
{ 
    echo 'Het selecteren van de eerste database is niet gelukt.'.PHP_EOL; 
    exit(1); // Eventueel een andere foutcode :)
} 

// We kunnen een query loslaten 
$query  = "SELECT `SoldierName` FROM `tbl_playerdata`"; 
$result = mysql_unbuffered_query($query, $conn); // Niet gelijk alles in memory laden, connectie meegeven 
         
if(!$result) // Controleer of de query uitvoerbaar was 
{ 
    echo 'Er ging iets mis met het draaien van de query.'.PHP_EOL; 
    exit(1); // Do I have to say more?
}


// Weet niet zeker of dit kan, misschien toch 2 connecties zie ook de rest van mijn commentaar...
if(!mysql_select_db('ezstats', $conn)) // Controleer of verbinden met tweede database is gelukt 
{ 
    echo 'Verbinden met tweede database is niet gelukt.'.PHP_EOL; 
    exit(1);
} 

// Dit is erg belangrijk voor performance!
$commit = true;
if ( mysql_query('BEGIN TRANSACTION', $conn) === false )
{
    echo 'Het starten van de transactie is mislukt '.mysql_error().', nu gaat de performance zuigen...'.PHP_EOL;
}
// Vang de resultset op 
while($row = mysql_fetch_assoc($result)) 
{
    $player = mysql_real_escape_string($row['SoldierName']); // Escape de spelernamen waar noodzakelijk 
    $query2  = "INSERT INTO ezstats_players (name) VALUES ('". $player ."');"; 
    $result2 = mysql_query($query2, $conn); 
     
    if(!$result2) 
    { 
        echo 'Het invoeren van '. htmlspecialchars($row['SoldierName']) .' is niet gelukt, waarschijnlijk al in de tabel.<br>';
    } 
    else 
    { 
        echo 'Speler '. htmlspecialchars($player) .' is succesvol aan de EZStats toegevoegd<br>'; 
    } 
}

// Transactie gestart
if ( $commit ) {
    // Dus ook even commiten:
    if ( mysql_query('COMMIT', $conn) === false ) {
        echo 'Je bent de lul want er kan niet gecommit worden. :)'.PHP_EOL;
    }
}

mysql_close($conn);


Mogelijk heb je 2 connecties nodig om dit script uit te kunnen voeren omdat je nog aan 't lezen bent terwijl je ook wilt schrijven.

Wat er nu echt praktisch veranderd is:
* Ik maak gebruik van unbuffered_query, dit zorgt ervoor dat je geheugen verbruik laag is, omdat php nu niet het COMPLETE resultaat in memory heeft;
* Ik maak gebruik van Transacties, dit zorgt er voor dat MySQL alle commando's in 1 keer wegschrijft, dit scheelt een hoop overhead.

Waar zou je naar moeten kijken voor de toekomst:
* Een abstractie laag bovenop je database, rauwe SQL code schrijven vraagt om beveiligings problemen, een mysql_real_escape_string is snel vergeten en ook takke veel typ werk, zoek naar MySQLi, Zend_Db of zelfs Doctrine;
* Dit zou je echt via een cronjob moeten doen en niet via een browser.

Hoop dat je er wat mee kan en doet, was een hoop tikwerk :)

[ Voor 0% gewijzigd door ReenL op 01-01-2011 20:30 . Reden: Php-code tag :) ]


Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Ik hoef het niet uitgebreid te hebben en Bad Company 2 zal ik vast ook niet tot in den treuren blijven spelen.
Ook is het natuurlijk afhankelijk hoe lang die server blijft draaien.

Ik weet niet of het een groot probleem is, maar de ontvangende tabel (ezstats.ezstats_players) heeft als storage engine MyISAM. De verzendende tabel is dan weer wel INNODB en als ik goed ingelicht ben, heeft INNODB toch als enige binnen MySQL transaction support?

Een DBAL is daardoor gigantisch overbodig en zorgt er juist voor dat het qua performance achteruit gaat, zo is mijn ervaring (was paar jaar terug althans met PEAR::DB dacht ik). Het geheel draait op een Debian testing, deze installeert standaard MySQLi voor PHP.

Uiteindelijk wil ik dit uiteraard zonder browser, maar via CLI aanpakken mbv cronjob idd. :)

EDIT: Zojuist tabel ezstats.ezstats_players omgezet naar InnoDB, maar krijg de foutmelding dat de transactie niet gelukt is.

EDIT2: Ah, BEGIN TRANSACTION moet START TRANSACTION of TRANSACTION BEGIN zijn... :)

EDIT3: Ik heb het script gekopiërt en aangepast waar nodig, nu zijn de foutmeldingen weg, maar blijft het scherm wit. Terwijl de while loop toch echt zou moeten aangeven, of het gelukt is of niet., de code die hierdoor is ontstaan is:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
$host = 'localhost'; // Server 
$user = 'usert';      // Gebruikersnaam 
$pass = 'pass';  // Wachtwoord 

$conn = mysql_connect($host, $user, $pass); 
if(!$conn) // Maak connectie met database en controleer of gegevens goed zijn 
{ 
    echo 'Het maken van de verbinding was niet goed.'.PHP_EOL; // Newline :)
    exit(1); // Exit met een foutcode, geen onnodige else waardoor alles 1000 tabs naar rechts staat
}

// Selecteer de benodigde database 
if(!mysql_select_db('ProConStatsLog', $conn)) // Controleer of het selecteren van de database gelukt is. + connectie
{ 
    echo 'Het selecteren van de eerste database is niet gelukt.'.PHP_EOL; 
    exit(1); // Eventueel een andere foutcode :)
} 

// We kunnen een query loslaten 
$query  = "SELECT `SoldierName` FROM `tbl_playerdata`"; 
$result = mysql_unbuffered_query($query, $conn); // Niet gelijk alles in memory laden, connectie meegeven 
         
if(!$result) // Controleer of de query uitvoerbaar was 
{ 
    echo 'Er ging iets mis met het draaien van de query.'.PHP_EOL; 
    exit(1); // Do I have to say more?
}


// Weet niet zeker of dit kan, misschien toch 2 connecties zie ook de rest van mijn commentaar...
$conn2 = mysql_connect($host, $user, $pass);
if(!mysql_select_db('ezstats', $conn2)) // Controleer of verbinden met tweede database is gelukt 
{ 
    echo 'Verbinden met tweede database is niet gelukt.'.PHP_EOL; 
    exit(1);
} 

// Dit is erg belangrijk voor performance!
$commit = true;
if ( mysql_query('START TRANSACTION', $conn) === false )
{
    echo 'Het starten van de transactie is mislukt '.mysql_error().', nu gaat de performance zuigen...'.PHP_EOL;
}
// Vang de resultset op 
while($row = mysql_fetch_assoc($result)) 
{   
    $player = mysql_real_escape_string($row['SoldierName']); // Escape de spelernamen waar noodzakelijk 
    $query2  = "INSERT INTO ezstats_players (name) VALUES ('". $player ."');"; 
    $result2 = mysql_query($query2, $conn2); 
     
    if(!$result2) 
    { 
        echo 'Het invoeren van '. htmlspecialchars($row['SoldierName']) .' is niet gelukt, waarschijnlijk al in de tabel.<br>';
    } 
    else 
    { 
        echo 'Speler '. htmlspecialchars($row['SoldierName']) .' is succesvol aan de EZStats toegevoegd<br>'; 
    } 
}

// Transactie gestart
if ( $commit ) {
    // Dus ook even commiten:
    if ( mysql_query('COMMIT', $conn) === false ) {
        echo 'Je bent de lul want er kan niet gecommit worden. :)'.PHP_EOL;
    }
}

mysql_close($conn);
mysql_close($conn2);
?>
Het lijkt er dus op, dat er wel degelijk 2 connecties nodig zijn, maar ik zie even niet wáár ik die tweede connectie moet aanvangen, of wáár ik naar de verkeerde connectie verwijs.

[ Voor 105% gewijzigd door CH4OS op 01-01-2011 22:39 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Als de data niet wijzigt kun je het toch met een is_synced veld doen? Wat dan in een batch geinsert wordt update je met is_synced = 1 en in je select query gebruik je dan WHERE is_synced = 0. Ik zou sowieso een insert met multiple values gebruiken INSERT INTO ... VALUES(), VALUES(), ...

Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Topicstarter
Verwijderd schreef op zondag 02 januari 2011 @ 11:59:
Als de data niet wijzigt kun je het toch met een is_synced veld doen? Wat dan in een batch geinsert wordt update je met is_synced = 1 en in je select query gebruik je dan WHERE is_synced = 0. Ik zou sowieso een insert met multiple values gebruiken INSERT INTO ... VALUES(), VALUES(), ...
De data wijzigt inderdaad niet en ik hoef alleen maar het veld van de namen over te zetten. Probleem is alleen dat deze velden in beide databases / tabellen anders heten, weet niet of die is_synced een aparte functie binnen MySQL is, of dat je er een nieuwe column mee bedoeld? Ik denk dat ik dat maar ga doen inderdaad, dat scheelt op de lange duur al een heleboel, al kost het mij wel een extra insert query, maar goed, dat hoeven er dan niet zoveel te zijn. Zeg maar een soort baten en kosten en zo. ;)

Mja, het mooiste is inderdaad om alles in 1 INSERT INTO te doen, maar ik vang de namen eerst al op met een SELECT hé, gaat het dan niet extra performance kosten om die ene grote insert query te bouwen? ;)

[ Voor 17% gewijzigd door CH4OS op 02-01-2011 12:47 ]


Acties:
  • 0 Henk 'm!

  • -Sander1981-
  • Registratie: November 2000
  • Laatst online: 22-04-2020
Ik ben meer thuis in T-SQL, maar werkt deze query niet?
SQL:
1
2
3
INSERT INTO [Table1] (naam) 
(SELECT speler FROM [Table2]
 WHERE speler NOT IN (SELECT naam FROM [Table1]))

Misschien niet de allersnelste query, maar zou in dit geval moeten voldoen...

I don't have a solution; but I do admire the problem.


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Met multi insert kan je out of memory raken.

De inserts en de transacties moeten met connectie2, de select met connectie 1.

Je kunt wel een multi insert doen, voor 10-20 records, scheelt waarschijnlijk iets aan data-uitwisseling tussen php en mysql. En omdat je het per 20 raak je ook niet out of memory. Ik denk alleen dat je het verschil niet kan merken.

Tables die geen transacties ondersteunen kun je write locken:
LOCK TABLES tabel WRITE;
INSERT INTO ...
UNBLOCK TABLES:

Zie ook:
http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

[EDIT]
Geen NOT IN(SELECT ..) gebruiken, de performance daarvan is dramatisch, en wordt alleen maar slechter als de data in de 2e select groter wordt.

[ Voor 12% gewijzigd door ReenL op 03-01-2011 20:41 ]


Acties:
  • 0 Henk 'm!

  • Davio
  • Registratie: November 2007
  • Laatst online: 06-01 16:46
Ik wil nog even toevoegen over het maken van zo'n verbinding met een db dat de 'or die("Whatever")'-constructie veel gebruikt wordt.

PHP:
1
2
3
4
5
6
7
8
<?php

// Dankzij de shortcircuit wordt het stuk na de or alleen uitgevoerd als het eerste stuk false geeft
// Volgens de documentatie van mysql_connect: Returns a MySQL link identifier on success or FALSE on failure. 
$conn = @mysql_connect($h, $u, $p) or die("Connection failed.");
// De @ voor de functie onderdrukt de standaard warnings en errors die door de functie gegenereerd worden.
// De die-functie zorgt ervoor dat je script afsterft en nog een laatste melding geeft.
?>


Zo kun je een if-block voorkomen.

Als je nog het één en ander wilt opruimen, zou je een if-block willen gebruiken, maar PHP is vrij netjes met de Garbage Collection en als je script is afgelopen, zorgt PHP er zelf voor dat alles wat niet meer nodig is vanzelf wordt opgeruimd.

Als je een mysql_pconnect() hebt ipv mysql_connect, maak je echter een persistente verbinding aan die open blijft als het script afloopt, hier moet je wel op letten. Maar dit levert dan weer andere problemen op en daarom raad ik (zeker beginners) aan om niet zonder meer mysql_pconnect() te gebruiken, maar gewoon mysql_connect.
Pagina: 1