سؤال

الهدف من ذلك هو الحصول على برنامج نصي PHP مع قسم معين من الكود لا يمكن تنفيذه إلا بواسطة مؤشر ترابط/عملية واحدة في وقت واحد.

بعض القيود:

  • Semaphores غير متوفرة على نظامي
  • يذكر الدليل أنه لا يمكن الاعتماد على قطيع () في خوادم متعددة الخيوط ، لذلك قطيع () خارج. (أكد هذا)

لذلك يعتقد أنه سيكون من الممكن (لماذا لا؟) استخدام MySQL للمزامنة ، لكنني أحصل على نتائج غير متوقعة.

للاختبار ، لدي علامات تبويب متصفح مفتوحة مع اختبار البرنامج النصي.

mysql_connect ($ dbhost ، $ dbuserName ، $ dbPassword) ؛ mysql_select_db ($ database_name) ؛

$ sql = "حدد my_val من my_table أين my_var= 'الحالة' "؛ $ result = mysql_query ($ sql) أو يموت (mysql_error ()) ؛ $ row = mysql_fetch_array ($ result ، mysql_assoc) ؛ echo" الحالة هي: ". $ row ['my_val']."
n "؛ mysql_free_result ($ result) ؛

إذا ($ row ['my_val'] == 'Running') يموت ("العملية تعمل بالفعل! ') ؛

// دخول القسم الحرج

$ sql = "تحديث my_table تعيين my_val= "الجري" حيث my_var= 'الحالة' "؛ mysql_query ($ sql) ؛

النوم (10) ؛ // القيام ببعض العمل هنا. echo 'الانتهاء من العمل
';

// اترك القسم الحرج. دع الآخرين يعرفون $ sql = "تحديث my_table تعيين my_val= 'not_running' حيث my_var= 'الحالة' "؛ mysql_query ($ sql) ؛

الطاولة هي:

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'
) 

أذهب إلى علامة التبويب المتصفح الأولى والوصول إلى البرنامج النصي. أنتظر 5 ثوانٍ ، انتقل إلى علامة التبويب الأخرى والوصول إلى البرنامج النصي بحيث يتم تشغيل كلا البرامج النصية بالتوازي. أتوقع أن تنتظر علامة التبويب الأولى ، ويجب خروج علامة التبويب الثانية بعد الاستعلام الأول. ومع ذلك ، تنتظر كلتا التبويب على خط Sleep (). هذا يعني أن الاستعلام الأول يعيد دائمًا "not_running".

بعض الأشياء الغريبة:

  • عندما أكرر التجربة أعلاه ، أقوم بتشغيل كلا علامات التبويب في Firefox ، ثم في نوع المتصفح المختلفة الثالثة ، كما يقول Chrome ، ثم يعمل! (تم ضبط الحالة على التشغيل أثناء النوم ، يخرج البرنامج النصي مبكرًا عند تشغيل الحالة)
  • عندما أكرر التجربة أعلاه باستخدام نوافذ سطر الأوامر المختلفة ، وقم بتشغيل البرنامج النصي من سطر الأوامر ، فإنه يعمل!
  • أتحقق من phpmyadmin أثناء انتظاره ، يتم تحديث الحالة بشكل صحيح.

لقد جربت كل شيء ، وقفل الجدول ، والمعاملات ، وتعيين مستوى عزل المعاملة العالمية قراءة غير ملتزم ، وضبط autocommit = 1 ؛ ، ومع ذلك دائما نفس النتيجة.

هل يعرف أحد ما يحدث هنا؟ هل هناك أي حل جيد لهذه المشكلة؟

تم اختبار الأنظمة: - Win ، MySQL 5.0 ، PHP 5.3 - Linux ، MySQL 5.0.91 -Community -Log ، PHP 5.2.12

أنا عالق تمامًا هنا ، شكرًا على إلقاء نظرة!


تحديث:

شكرا لتقديم إجاباتك - ما زلت لا أستطيع حل هذه المشكلة. فيما يلي الرمز مع get_lock () و session_write_close () كما هو مقترح: لقد جربت أيضًا قفل مستوى الصف والمعاملات ومستويات العزل المختلفة. ربما لا يمكن القيام به؟

session_write_close();

mysql_connect($dbhost, $dbusername, $dbpassword);
mysql_select_db($database_name);

$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); if ($row['my_val']=='RUNNING') die ('process is already running!'); // entering critical section $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();
هل كانت مفيدة؟

المحلول

نافذة المتصفح الثانية لا تتدلى على sleep يأمر. إنه أمر يحظر لأن الجلسات تمنع (وبالتالي تحاول فتح الجلسة نفسها). يمكنك إغلاق الجلسة الحالية إذا لم تعد بحاجة إليها (وبالتالي لا تريد حظرها) session_write_close...

نصائح أخرى

MySQL لديه وظيفة تسمى get_lock.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top