تمثل السجلات المُدرجة في جدول QueryRunner الاستعلامات التي ينفذها المحرك.
يمكن استخدام المحرك للتنفيذ غير المتزامن للاستعلامات، وتنفيذ الاستعلامات المُولَّدة على دفعات،
وتوجيه الاستعلامات إلى العناقيد البعيدة، واختبارات الأداء، والتشويش، والاختبار باستخدام حركة المرور الظلية.
إنشاء جدول
CREATE TABLE runner
(
query String,
database String,
settings Map(LowCardinality(String), String)
)
ENGINE = QueryRunner
SETTINGS
cluster = 'cluster_name',
shard = '1',
mode = 'asynchronous',
threads = 4,
max_queue_size = 1000
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }];يجب إنشاء الجدول باستخدام مجموعة فرعية من الأعمدة المسموح بها: query، وdatabase، وsettings.
العمود query إلزامي، أما الأعمدة الأخرى فاختيارية.
| العمود | النوع | المعنى |
|---|---|---|
query |
String |
الاستعلام المطلوب تنفيذه. |
database |
String |
قاعدة البيانات الافتراضية للاستعلام. إذا كانت فارغة، فستُستخدم قاعدة البيانات الافتراضية للخادم. |
settings |
Map(String, String) |
الإعدادات المُطبَّقة على الاستعلام. |
إعدادات المحرّك
| الإعداد | القيمة الافتراضية | المعنى |
|---|---|---|
cluster |
'' |
اسم العنقود الذي تُرسَل إليه الاستعلامات. وإذا كان فارغًا، تُنفَّذ الاستعلامات محليًا. |
shard |
'1' |
مؤشر يبدأ من 1 لجزء العنقود الذي تُرسَل إليه الاستعلامات، أو 'random' لاختيار جزء عشوائي لكل استعلام، أو 'all' لتشغيل كل استعلام على جميع الأجزاء. ويتطلب ذلك إعداد cluster. |
mode |
'asynchronous' |
في وضع synchronous، تعود عملية INSERT بعد اكتمال جميع استعلامات الدفعة المُدرَجة. وفي وضع asynchronous، تعود عملية INSERT بمجرد إدراج الاستعلامات في قائمة الانتظار. |
threads |
4 |
عدد الخيوط الخلفية التي تنفّذ الاستعلامات. |
max_queue_size |
1000 |
الحد الأقصى لعدد الاستعلامات في قائمة الانتظار. وعندما تمتلئ القائمة، تُهمَل الاستعلامات المُدرَجة حديثًا ويُسجَّل خطأ. |
التفاصيل
لا يسمح الجدول إلا باستعلامات INSERT.
تُنفَّذ الاستعلامات بأسلوب "fire and forget": ففي حال حدوث استثناء، لا تُجرى أي محاولات إعادة،
كما تُهمَل نتائج استعلامات SELECT (والطريقة الوحيدة للاحتفاظ بالنتائج هي INSERT SELECT).
ويمكن التحقق من نجاح كل استعلام في جدول system.query_log، حيث تُوسَم الاستعلامات التي يبدأها
هذا المحرك بالقيمة is_internal = 1 على الخادم المُبادِر.
تُحفَظ الاستعلامات الموضوعة في قائمة الانتظار في الذاكرة، ولا تستمر بعد إعادة تشغيل الخادم. وعند إيقاف تشغيل الخادم
(أو تنفيذ DROP/DETACH للجدول)، تُهمَل الاستعلامات التي لم تبدأ بعد. أما من بين
الاستعلامات الجاري تنفيذها بالفعل، فتُلغى تلك المُرسَلة إلى عنقود، بينما يُنتظَر اكتمال تلك التي تعمل
محليًا حتى تنتهي.
عندما يكون الاستعلام المراد تشغيله هو نفسه INSERT، يجب أن تكون بياناته مضمّنة مباشرة — INSERT ... VALUES (...)،
أو INSERT ... SELECT ...، أو INSERT ... FORMAT ... مع وجود البيانات في نص الاستعلام. أما INSERT الذي
يتوقع بياناته من دفق منفصل فهو غير مدعوم.
الوضع المحلي وSQL SECURITY
من دون إعداد cluster، تُنفَّذ الاستعلامات على الخادم المحلي.
ويُحدَّد المستخدم الذي تُنفَّذ باسمه هذه الاستعلامات بواسطة بند SQL SECURITY:
INVOKER(الافتراضي): تُنفَّذ الاستعلامات نيابةً عن المستخدم الذي نفّذINSERT.DEFINER: تُنفَّذ الاستعلامات نيابةً عن مستخدمDEFINERالمحدَّد. ونظرًا لأن الاستعلامات المُدرَجة قد تكون اعتباطية، فإن منحINSERTعلى جدول من هذا النوع يفوِّض جميع امتيازات هذا المستخدم.NONE: تُنفَّذ الاستعلامات بصلاحية وصول كاملة، من دون مستخدم. ويتطلب ذلك امتيازALLOW_SQL_SECURITY_NONEعند إنشاء الجدول.
وضع العنقود
عند تحديد إعداد cluster، تُرسَل الاستعلامات إلى العنقود المحدد.
يُحدَّد الجزء المستهدف بواسطة shard: إمّا فهرس ثابت يبدأ من 1 ('1' افتراضيًا)، أو 'random' لاختيار
جزء عشوائي لكل استعلام، أو 'all' لتشغيل كل استعلام على كل جزء في العنقود. وتُختار نسخة متماثلة داخل
الجزء وفقًا لإعداد load_balancing الخاص بالخادم.
يضبط العمود database قاعدة البيانات الافتراضية للاتصال بالخادم البعيد. وبما أن
قاعدة البيانات الافتراضية تُضبط مرة واحدة لكل اتصال، فإن كل قيمة database مختلفة تستخدم
مجموعة اتصالات خاصة بها، تُنشأ عند أول استخدام ويُعاد استخدامها طوال عمر الجدول.
لا يكون لـ DEFINER و SQL SECURITY تأثير إلا في الوضع المحلي، ويُعد الجمع بينهما وبين
إعداد cluster خطأً. وعلى الخوادم البعيدة، تُوثَّق الاستعلامات باستخدام
بيانات الاعتماد من إعدادات العنقود، وتُشغَّل كاستعلامات أولية عادية: وتُسجَّل في
system.query_log مع is_initial_query = 1 ومعرّف query_id خاص بها (من دون ربطها بعملية INSERT التي
أنتجتها). وعلى الخادم البادئ، تُسجَّل الاستعلامات الموجَّهة في system.query_log
مع is_internal = 1.
ولأن المحرك يتجاهل نتائج الاستعلام، فإنه يشغّل دائمًا الاستعلامات الموجَّهة باستخدام
discard_query_data = 1، لذا لا تُنقَل بيانات نتائج استعلامات SELECT عبر الشبكة
(وهذا يتجاوز أي قيمة discard_query_data مُعيَّنة في العمود settings).
انتظار اكتمال الاستعلامات
في الوضع غير المتزامن، يمكن استخدام الاستعلام التالي للانتظار إلى أن يكتمل كل استعلام أُرسل إلى الجدول حتى الآن:
SYSTEM WAIT QUERY RUNNER runner;مثال
إعادة تنفيذ أحدث استعلامات SELECT من سجل الاستعلامات:
INSERT INTO runner (query, database, settings)
SELECT query, current_database, Settings
FROM system.query_log
WHERE type = 'QueryFinish' AND is_initial_query AND NOT is_internal AND query_kind = 'Select'
AND event_time > now() - INTERVAL 1 HOUR;