PostgreSQL synchronous replication

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Keiichi
  • Registratie: Juni 2005
  • Laatst online: 08-10 09:57
Ik probeer een postgresql cluster te maken met 1 master en 1 slave node. Reads zullen over de nodes gebalanced worden, master krijgt de writes voor z'n kiezen en repliceert deze naar de slave.

Hierbij heb ik synchrone replicatie (commit) ingeschakeld met 'synchronous_commit = remote_write' op de master. Dit werkt, als ik de slave uitzet dan blijft een insert hangen totdat ik de slave terug aanzet.

De balancing zou via pgpool moeten gaan lopen, maar voor een test heb ik het volgende script:

code:
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
<?php

$pdo1 = new PDO("pgsql:dbname=test01;host=postgres1", "testuser", "");
$pdo2 = new PDO("pgsql:dbname=test01;host=postgres2", "testuser", "");

$pdo1->query("TRUNCATE test01");
 
$i=0;
while(true) {
  echo "loop $i\n";
  //$pdo1->beginTransaction();
  $pdo1->query("INSERT INTO test01 VALUES ($i)");
  //$pdo1->commit();
  $data = $pdo2->query("SELECT * FROM test01 WHERE col1 = $i");
  
  $fetched = $data->fetchAll();
  $count = count($fetched);
  if ($count !== 1) {
    echo "OH NOEEEESS $i (count was $count)\n";
    var_dump($fetched);
    sleep(1);
    var_dump($pdo2->query("SELECT * FROM test01 WHERE col1 = $i")->fetchAll());
    exit;
  }
  $i++;
}


De postgresql server heeft overigens niets meer dan alleen een database test01 met een tabel test01. De verwachting is dat altijd de data die net op de master ingevoerd is aanwezig is op de slave. De commit zou moeten wachten tot deze op de slave ook weggeschreven is.

Dit is niet het geval.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
keiichi@linux:~# php postgres.php 
loop 0
loop 1
OH NOEEEESS 1 (count was 0)
array(0) {
}
array(1) {
  [0] =>
  array(2) {
    'col1' =>
    int(1)
    [0] =>
    int(1)
  }
}


Wanneer het verkeerd gaat varieert ook, laatste testen binnen 10x, eerdere testen vandaag pas na 20.000x

Doe ik hier iets verkeerd? Heb ik verkeerd idee bij synchronous replication bij postgresql?

Het probleem is (vanzelfsprekend) niet als de 2 queries in 1 commit gaan, pgpool (wat ik ook wil gebruiken) zal de queries in een commit alleen op de master doen. Echter de applicatie die er gebruik van gaat maken doet dit niet en staat hier buiten discussie.

Solar @ Dongen: http://solar.searchy.net/ - Penpal International: http://ppi.searchy.net/


Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 10-10 23:43
Het 'probleem' kan je ook tegenkomen als je geen replicatie gebruikt maar gewoon twee verbindingen naar dezelfde psql instantie.

Andere transacties kunnen in het standaard isolation level in PostgreSQL oudere versies van data zien, ook in het moment in tijd dat de ene transactie al is gereturned van een commit. Een commit betekent (standaard) dat de data is veiliggesteld en bij een crash naar een consistente staat kan worden teruggebracht, het is geen garantie dat de data vanaf dat exacte moment voor andere transacties (zelfs al starten ze een fractie later) zichtbaar is.

Voor redelijk consistent gedrag gebruik je in een php script gewoon enkele transactie. Jouw voorbeeldcode zou je dus nooit in het echt maken.

De vraag is of het heel erg is dat een concurrent ander php request van de applicatie oudere versie van data kan zien. Als je er over nadenkt zal dit vaak niet zo erg zijn. Is dat wel zo dan moet je daar wel de performanceprijs voor betalen door expliciete locks of transactions met serializable isolation level te gebruiken.

[ Voor 6% gewijzigd door matthijsln op 10-02-2016 23:42 ]