PHP és MySQL

Tags: #<Tag:0x00007f8a1ee76300> #<Tag:0x00007f8a1ee75f68> #<Tag:0x00007f8a1ee75bf8>

A tisztelt webfejlesztő hölgyeket és urakat kérdezném. @esojaro

Van a mi csodálatos SAP-nk, ami SOAP-on beszélget a webshoppal. A webshop alatt van egy MySQL adatbázis, ami a termékadatokat letárolja a web számára. Ez 15 percenként frissül.

Én azt látom a PHP-ban, hogy az adatbázis termék táblájának minden sorát egy egyedi SQL UPDATE végzi. És ha jól gondolom, ezért van az, hogy a frissítés alatt a frontenden a termékek el-el tűnnek majd vissza. Rossz pillanatban még 404-es hibára is futhat a nézelődő egy-egy termékoldal újratöltésekor.

Egy ilyen adatbázis frissítést nem szokás tranzakcióba rakni? Vagy valami cache-elést csinálni, hogy az adatbázis írása ne tűnjön föl a frontenden?

Igazabol minden sql muveletet illik tranzakcioba tenni. Ha haszaltok valamilyen framework-t az oldal alatt az valoszinuleg ezt elvegzi nektek a hatterben.

PHPmyAdminban látszik, hogy tranzakcióban vannak-e update-elve a sorok? Jelenleg csak annyit látok, hogy a SHOW FULL PROCESSLIST-ben pörögnek az UPDATE-ek termékenként.

Ez egy 100%-ban egyedi webshop az SAP mellé, semmi jel nem utal arra, hogy bármilyen framework lenne használva.
SOAP válaszból lesz egy PHP objektum és egy foreach-csel végigszalad rajta a script. Ami nincs még az adatbázisban INSERT-tel beteszi, ami benne van azt egy UPDATE-tel frissíti.

A phpMyAdminban nem, a kódban kellene olyasminek lenni az update környékén, hogy beginTransaction, commit, revert.

Egyébként valami más lesz a gond szerintem, mert egy update csak akkor fog neked 404-et okozni, ha letörlöd az egész cuccot és újra létrehozod. Elmondásod szerint nem ez van.

De szerintem jelezd a fejlesztő cégnek, hogy milyen probléma van, és ők majd kidebugolják.

Azért nyugtass meg, hogy nem az van, hogy minden terméket frissítetek negyed óránként, akkor is, ha nem változott.

Megnyugtatlak, hogy igen, minden termék, minden negyedórában frissítve van, akkor is ha nem változott semmi. :-P

Ez talán nem a legjobb megoldás… Nyilván nem annyira egyszerű a kérdés az SAP miatt, nem tudom, mennyire képes az kifelé kommunikálni. Utánanézek.

Ez nem a webesek sara, nincs olyan SOAP hívás, ami csak a változásokat adja vissza, amelyek történtek a termékadatbázisban.

Igen, meg kellene fordítani, a webshophoz kellene egy REST api, amit az SAP-nak kellene hívnia, ha valami megváltozott. Az SAP NetWeaver tud REST-tel kommunikálni, de nem tudom, hogy a Business One-ban benne van-e.

Viszont, ha ez nem megoldható, akkor sem kellene ész nélkül lefrissíteni mindent.

  1. Lekéred az összes termék adatát a mysql-ből. (Ez eddig egy darab SELECT) Lesz egy array vagy egy object belőle.
  2. Lekéred az adatokat a SAP-ből, átkonvertálod abba a formátumba, amiben a termékadatok vannak.
  3. Soronként összehasonlítod a két objectet, és csak akkor küldesz a db-be update-et arra az egy termékre, ha eltérést találsz. Hiányzó cucc esetén insert.

http://php.net/manual/en/function.array-diff-assoc.php

Pseudo code, feltételezve, hogy a mysql termék id eltér az sap-s id-től, de az is el van tárolva hozzá:

$mySqlProducts = [];
$data = query('select * from products');
forEach($data as $currentProduct){
 $mySqlProducts[$currentProduct->sap_id] = $currentProduct;
}

$sapProducts = getSoapData()->toArray();

forEach($sapProducts as $product){
 $productInMysql = $mySqlProducts[$product->id];
   if($productInMysql === null){
      addNewProduct();
      continue;
   }
   if(count(array_diff_assoc($product, $productInMysql)) > 0){
  
     updateProduct($productInMysql->id);

   }
}

Nyilván, ha vannak timestampek a product adatokban, azt ki kell venni, mert azok mindenképpen el fognak térni.

Egyébként, ha az SAP eltárolja a a termék keletkezésének és módosításának idejét (ami kb. ezer százalék), akkor meg még egyszerűbb, mert csak azokat kell lekérni, amiknek az ‘updated_at’ paramja nagyobb, mint az utolsó ellenőrzés időpontja. Ez csak akkor megy, ha egy termék létrehozásakor az updated_at megkapja a created_at értékét, de ez erősen valószínű.

$checkTime = now();
//last check's time is stored in the db, or in a file, or whatever
$lastCheck = getLastCheckTime();

//parameterizing soap request
  <p_filter xsi:type="soap:filter" xmlns:soap="http://soap.url">
        <!--You may enter the following 5 items in any order-->
        <type xsi:type="xsd:string">cond</type>
        <column xsi:type="xsd:string">updated_at</column>
        <operator xsi:type="xsd:string">&gt;</operator>       
        <value xsi:type="xsd:string">$lastCheckTime</value>
     </p_filter>

//soap processing here...
//saving check time 
saveCheckTime($checkTime);

Ugyanarra gondoltunk. :-) Megnézem, hogy ki tudom-e vezetni a SOAP-ba ezeketet a mezőket.

Én arra gondoltam, hogy a php-ből küldött soap kérésbe kell beletenni a feltételt, így a válasz már nem fogja tartalmazni az összes terméket.

Nem igazán mysql, de majdnem. :)
A lényeg, hogy mysql-lel megcsináltam, hogy a query transactionnel működjön, pl

$mysqli->begin_transaction(MYSQLI_TRANS_START_READ_ONLY);

A gond az, hogy az egyik cél szerveren mariadb van.
A teszt gépemre felraktam a legfrissebb mariadb-t:

mysql  Ver 15.1 Distrib 10.3.9-MariaDB, for osx10.14 (x86_64) using readline 5.1

A cél szerveren pedig:

mysql  Ver 15.1 Distrib 10.0.35-MariaDB, for Linux (x86_64) using readline 5.1

A gond az, hogy valószínűleg nem jól ismeri fel a PHP verziót és emiatt azt mondja, hogy nem működik:

PHP Warning:  mysqli::begin_transaction(): This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required in /path/to/file.php on line 37

Mit lehet ezzel kezdeni azon kívül, hogy kikapcsolom a transaction, pedig azt nem akarom? :D

Azt hiszem, hogy rájöttem, hogy valójában nem tudja ezt a funkciót a mariadb, ugyanis még a teszt verzió is csak 5.5.0-ra épül. Ennek segítségével tudtam csekkolni:

$dbHandle->server_version >= 50605
1 Like

Valami fura, mert MariaDB-nel 10.0-tol van START TRANSACTION-nel READ ONLY es READ WRITE, viszont csak InnoDB eseten. Szoval, 10.0 eseten mar lennie kellene. Milyen PHP verzio?

Van innodb, ez volt az első amit megnéztem. PHP 7.1.x amúgy az a PHP, ami macos-szel jön alapból. Az iMacen a legfrissebb 10.14 van már.
A cél szerveren most fogalmam sincs, hogy milyen PHP.
De nekem eleve fura, hogy 5.5.5-tel kezdődik a verzió szám.

MariaDB eseten ne erdekeljen a mysql verzioszam. A 10-es mariadb boven tudja azt, amit az 5.6-os MySQL. https://mariadb.com/kb/en/library/mariadb-vs-mysql-compatibility/ Ez inkabb nekem mysqli bugnak tunik. Es tenyleg: http://php.net/manual/en/mysqli.begin-transaction.php#122775 Az Oracle fele workarund tokonszurja a mysqli-t.