الطريقة الصحيحة لاستخدام MySQL لتعيين المهام لعمليات العمال

StackOverflow https://stackoverflow.com/questions/664774

سؤال

لدي قائمة ضخمة من عناوين URL في جدول MySQL Innodb ، وعمليات العمال التي تستفسر عن MySQL لمجموعة من عناوين URL للمعالجة. يجب تمييز عناوين URL على الفور على أنها تتم معالجتها ، بحيث لا تضيع عمليات العمال الأخرى الموارد من خلال البدء في معالجة نفسها.

حاليا أقوم بذلك أولاً للحصول على بعض عناوين URL:

SELECT DISTINCT url FROM urls WHERE task_assigned is NULL ORDER BY id LIMIT 100

ثم في الكود أحلق بسذاجة من خلال كل من عناوين URL هذه لتمييزها على أنها تتم معالجتها:

UPDATE urls SET task_assigned = NOW() WHERE url = ? COLLATE utf8_bin

أنا أدرك تمامًا مدى سخافة هذا. والأهم من ذلك أنه لا يوجد ضمان بأن عملية عامل أخرى لن تحاول الحصول على قائمة في منتصف تحديثاتي. ما هي الطريقة الجميلة للقيام بذلك؟ هل يجب أن أجعلها معاملة ، كيف؟

هل كانت مفيدة؟

المحلول

يظهر ما يلي (من خلال لمحة سريعة في دليل MySQL 5) ليكون متاحًا في MySQL ؛ لست متأكدًا مما إذا كان هذا هو أفضل طريقة ، ولكنه نهج استخدمته من قبل في postgresql:

BEGIN TRANSACTION;
SELECT DISTINCT url FROM urls WHERE task_assigned is NULL ORDER BY id LIMIT 100 FOR UPDATE;
UPDATE urls SET task_assigned = NOW() WHERE url IN [list of URLs] COLLATE utf8_bin;
COMMIT;

في الواقع في postgresql سأستخدم أ غير مرتبطة تحديث بيان مع جملة Returning of Update ، أخذ مكان SELECT ، ولكن هذا هو امتداد خاص بـ postgreSQL.

إحدى المشكلات المحتملة التي أراها مع نهجك هي عناوين URL المكررة: إذا كان عنوان URL http://www.example.com/ يظهر مرتين في طاولتك ، على سبيل المثال مع IDS 23 و 42 ، سيتم إرجاعه مع أحد هذين المعرفين بواسطة Select لكن التحديث سيؤثر على كلا الصفين. لا أعرف ما إذا كان هذا السلوك منطقيًا في تطبيقك ؛ من المحتمل أن أضع نوعًا من القيود الفريدة على عناوين URL حتى لا يحدث ذلك ، ثم استخدام قائمة بالمعرفات ، وليس عناوين URL ، في IN بند (الذي يجب أن يكون أسرع).

نصائح أخرى

ربما يجب عليك فقط تحديد جميع عناوين URL أولاً ثم استخدام المواضيع لتحليلها بشكل غير متزامن؟

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