MySQL ile beklenmeyen sonuçlar - Bir crtitical bölümü modernleşmek için PHP kilitleme

0 Cevap php

Amacınız sadece bir defada bir iplik / işlem ile çalıştırılabilir kod belirli bir bölümü ile bir PHP komut dosyası var olmaktır.

Bazı kısıtlamalar:

  • benim sistemde mevcut değil semaforlar
  • Manuel flock () () dışında çoklu iş parçacıklı sunucularda güvendi, böylece akın edilemez bahseder. (Onaylamıştır)

Bu yüzden senkronizasyon için MySQL kullanmak mümkün (neden?) Olacağını düşündüm, ama beklenmedik sonuçlar alıyorum.

Test etmek için, komut test.php ile iki tarayıcı sekme açık

mysql_connect($dbhost, $dbuserisim, $dbpassword); mysql_select_db($database_isim);

$sql = "SELECT my_val FROM my_table WHERE my_var='status' "; $result = mysql_query($sql)or die(mysql_error()); $row = mysql_fetch_array($result, MYSQL_ASSOC); echo "status is:".$row['my_val']."
\n"; mysql_free_result($result);

($ row ['my_val'] == 'ÇALIŞIYOR') die if ('süreci zaten çalışıyor!');

/ / Kritik bölümüne girerek

$sql = "UPDATE my_table SET my_val='RUNNING' WHERE my_var='status' "; mysql_query ($sql);

sleep(10); // do some work here. echo 'finished work
';

// leave critical section. let the others know $sql = "UPDATE my_table SET my_val='NOT_RUNNING' WHERE my_var='status' "; mysql_query ($sql);

Tablo:

CREATE TABLE `my_table` (
  `my_var` varchar(255) NOT NULL default '',
  `my_val` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`my_var`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `my_table`
VALUES (
'status', 'NOT_RUNNING'
) 

Ben ilk tarayıcı sekmesine gidin ve komut dosyası erişmek. Ben diğer sekmesine gidin ve her iki komut paralel çalışacak şekilde komut dosyası erişmek, 5 saniye bekleyin. Ben ilk sekme beklemek beklemek ve 2. sekme 1 sorgudan sonra çıkmalısınız. Ancak, her iki sekmeler uyku () hattı üzerinde bekleyin. Bu ilk sorgu her zaman 'NOT_RUNNING' döndüren demektir.

Bazı garip şeyler:

  • Ben yukarıdaki deneyi tekrarlamak zaman o çalışıyor, ben FireFox hem sekmeleri çalıştırın ve daha sonra 3 farklı tarayıcı türü, Chrome'u demek! (Durum çalışırken uyku, script erken çıkar ise durum ÇALIŞIYOR ayarlanır)
  • Ben iki farklı komut satırı pencereleri kullanarak yukarıdaki deneyi tekrarlamak ve komut satırından komut dosyasını çalıştırdığınızda, bu işe yarıyor!
  • Bu beklerken ben phpMyAdmin kontrol durumunu doğru güncellenir.

Ben SET autocommit = 1, GLOBAL işlem yalıtım düzey READ UNCOMMITTED SET, tablo kilitleme, işlemlerin her şeyi denedim, ama her zaman aynı sonucu.

Herkes burada neler olduğunu biliyor mu? Bu sorun için herhangi bir iyi bir çözüm var mı?

Systems tested: - Win, MySQL 5.0, php 5.3 - Linux, MySQL 5.0.91-community-log, php 5.2.12

Ben tamamen, burada bir göz için teşekkür şaşırıp!


GÜNCELLEME:

Thanks for submitting your answers - I still cannot solve this problem. Here is the code with GET_LOCK() and session_write_close() as suggested: I have also tried row level locking, transactions and different isolation levels. Perhaps it cannot be done?


session_write_close();

mysql_connect($dbhost, $dbuserisim, $dbpassword);
mysql_select_db($database_isim);

$sql = "CREATE TABLE IF NOT EXISTS `my_table`  (
  `my_var` varchar(255) NOT NULL default '',
  `my_val` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`my_var`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
";
mysql_query($sql)or die(mysql_error());

mysql_query ("SELECT get_lock('my_lock', 100)");

$sql = "SELECT my_val FROM `my_table` WHERE `my_var`='status' ";
$result = mysql_unbuffered_query($sql)or die(mysql_error());
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "status is:".$row['my_val']."
\n"; mysql_free_result($result); ($ row ['my_val'] == 'ÇALIŞIYOR') die if ('süreci zaten çalışıyor!'); / / Kritik bölümüne girerek $sql = "UPDATE `my_table` SET `my_val`='RUNNING' WHERE `my_var`='status' "; mysql_query ($sql); sleep(10); // do some work here. echo 'finished work
'; // leave critical section. let the others know //$sql = "UPDATE `my_table` SET `my_val`='NOT_RUNNING' WHERE `my_var`='status' "; $sql = "REPLACE INTO `my_table` (`my_var`,`my_val`) VALUES ('status', 'NOT_RUNNING')"; mysql_query ($sql); $result = mysql_query($sql)or die(mysql_error()); mysql_query ("SELECT release_lock('my_lock')"); die();

0 Cevap