الحالة 1: INSERT إلى قسم واحد، في جدول واحد، من عائلة MergeTree*
يكون ذلك معامليًا (ACID) إذا كانت الصفوف المُدرجة مُجمَّعة ومُدرجة ككتلة واحدة (راجع الملاحظات):
- Atomic: تنجح عملية INSERT بالكامل أو تُرفَض بالكامل: فإذا أُرسل تأكيد إلى العميل، فهذا يعني أن جميع الصفوف قد أُدرجت؛ وإذا أُرسل خطأ إلى العميل، فهذا يعني أنه لم يُدرج أي صف.
- Consistent: إذا لم تُنتهك أي قيود على الجدول، فستُدرج جميع الصفوف في عملية INSERT وتنجح العملية؛ وإذا انتُهكت القيود، فلن يُدرج أي صف.
- Isolated: يرى العملاء المتزامنون لقطة متسقة من الجدول — أي حالة الجدول كما كانت قبل محاولة INSERT أو بعد نجاحها؛ ولا تظهر أي حالة جزئية. العملاء داخل معاملة أخرى لديهم snapshot isolation، بينما العملاء خارج المعاملة لديهم مستوى العزل read uncommitted.
- Durable: تُكتَب عملية INSERT الناجحة إلى نظام الملفات قبل الرد على العميل، سواء على replica واحدة أو عدة replicas (ويتحكم في ذلك الإعداد
insert_quorum)، ويمكن لـ ClickHouse أن يطلب من نظام التشغيل مزامنة بيانات نظام الملفات مع وسيط التخزين (ويتحكم في ذلك الإعدادfsync_after_insert). - يمكن تنفيذ INSERT إلى عدة جداول بتعليمة واحدة إذا كانت العروض المادية متضمَّنة (أي تكون عملية INSERT من العميل إلى جدول لديه عروض مادية مرتبطة).
الحالة 2: INSERT في عدة أقسام ضمن جدول واحد من عائلة MergeTree*
كما في الحالة 1 أعلاه، مع هذا التفصيل:
- إذا كان الجدول يحتوي على عدد كبير من الأقسام وكان INSERT يشمل عدة أقسام، فإن الإدراج في كل قسم يكون معاملة مستقلة بحد ذاته
الحالة 3: INSERT إلى جدول Distributed واحد من عائلة MergeTree*
مثل الحالة 1 أعلاه، مع هذا التفصيل:
- إن عملية INSERT إلى جدول Distributed ليست تعاملية ككل، بينما يكون الإدراج في كل shard تعامليًا
الحالة 4: استخدام جدول Buffer
- عمليات الإدراج في جداول Buffer ليست ذرية ولا معزولة ولا متسقة ولا دائمة
الحالة 5: استخدام async_insert
مثل الحالة 1 أعلاه، مع هذا التفصيل:
- تكون خاصية الذرّية مضمونة حتى إذا كان
async_insertمفعّلًا وكانwait_for_async_insertمضبوطًا على 1 (القيمة الافتراضية)، ولكن إذا كانwait_for_async_insertمضبوطًا على 0، فلن تكون خاصية الذرّية مضمونة.
ملاحظات
- تُجمَّع الصفوف التي يُدرجها العميل بأي تنسيق بيانات في كتلة واحدة عندما:
- يكون تنسيق الإدراج قائمًا على الصفوف (مثل CSV وTSV وValues وJSONEachRow وغيرها)، وتحتوي البيانات على أقل من
max_insert_block_sizeصف (~1 000 000 افتراضيًا) أو أقل منmin_chunk_bytes_for_parallel_parsingبايت (10 MB افتراضيًا) عند استخدام التحليل المتوازي (وهو مُمكَّن افتراضيًا) - يكون تنسيق الإدراج قائمًا على الأعمدة (مثل Native وParquet وORC وغيرها)، وتحتوي البيانات على كتلة بيانات واحدة فقط
- يكون تنسيق الإدراج قائمًا على الصفوف (مثل CSV وTSV وValues وJSONEachRow وغيرها)، وتحتوي البيانات على أقل من
- قد يعتمد حجم الكتلة المُدرَجة عمومًا على العديد من الإعدادات (على سبيل المثال:
max_block_sizeوmax_insert_block_sizeوmin_insert_block_size_rowsوmin_insert_block_size_bytesوpreferred_block_size_bytesوغيرها) - إذا لم يتلقَّ العميل ردًا من الخادم، فلن يعرف ما إذا كانت المعاملة قد نجحت، وقد يعيد المعاملة باستخدام خصائص الإدراج exactly-once
- يستخدم ClickHouse داخليًا MVCC مع snapshot isolation للمعاملات المتزامنة
- تظل جميع خصائص ACID متحققة حتى في حالة إيقاف الخادم قسرًا أو تعطّله
- يجب تمكين insert_quorum عبر مناطق AZ مختلفة أو تمكين fsync لضمان متانة عمليات الإدراج في الإعدادات المعتادة
- لا يغطي "الاتساق" في مصطلحات ACID دلالات الأنظمة الموزعة؛ راجع https://jepsen.io/consistency، إذ تتحكم في ذلك إعدادات مختلفة (select_sequential_consistency)
- لا يشمل هذا الشرح ميزة المعاملات الجديدة التي تتيح معاملات كاملة الميزات عبر جداول متعددة وعروض مادية ولعدة عمليات SELECT وغير ذلك. (راجع القسم التالي حول Transactions وCommit وRollback)
المعاملات، وCommit، والتراجع
بالإضافة إلى الوظائف الموضحة في بداية هذا المستند، يوفّر ClickHouse دعمًا تجريبيًا للمعاملات وعمليات Commit ووظيفة التراجع.
المتطلبات
- انشر ClickHouse Keeper أو ZooKeeper لتتبّع المعاملات
- قاعدة بيانات atomic فقط (الافتراضي)
- محرك جدول MergeTree غير المُكرَّر فقط
- فعِّل دعم المعاملات Experimental بإضافة هذا الإعداد في
config.d/transactions.xml:<clickhouse> <allow_experimental_transactions>1</allow_experimental_transactions> </clickhouse>
ملاحظات
- هذه ميزة تجريبية، ومن المتوقع أن تطرأ عليها تغييرات.
- إذا حدث استثناء أثناء معاملة، فلا يمكنك تنفيذ
commitللمعاملة. ويشمل ذلك جميع الاستثناءات، بما فيها استثناءاتUNKNOWN_FUNCTIONالناتجة عن الأخطاء الإملائية. - المعاملات المتداخلة غير مدعومة؛ أنهِ المعاملة الحالية وابدأ معاملة جديدة بدلًا من ذلك
الإعدادات
تعتمد هذه الأمثلة على خادم ClickHouse أحادي العقدة مع تفعيل ClickHouse Keeper.
فعّل دعم المعاملات التجريبية
<clickhouse>
<allow_experimental_transactions>1</allow_experimental_transactions>
</clickhouse>التهيئة الأساسية لعقدة واحدة من خادم ClickHouse مع تفعيل ClickHouse Keeper
<clickhouse replace="true">
<logger>
<level>debug</level>
<log>/var/log/clickhouse-server/clickhouse-server.log</log>
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
<size>1000M</size>
<count>3</count>
</logger>
<display_name>node 1</display_name>
<listen_host>0.0.0.0</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<zookeeper>
<node>
<host>clickhouse-01</host>
<port>9181</port>
</node>
</zookeeper>
<keeper_server>
<tcp_port>9181</tcp_port>
<server_id>1</server_id>
<log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
<snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
<coordination_settings>
<operation_timeout_ms>10000</operation_timeout_ms>
<session_timeout_ms>30000</session_timeout_ms>
<raft_logs_level>information</raft_logs_level>
</coordination_settings>
<raft_configuration>
<server>
<id>1</id>
<hostname>clickhouse-keeper-01</hostname>
<port>9234</port>
</server>
</raft_configuration>
</keeper_server>
</clickhouse>مثال
تحقّق من تفعيل المعاملات التجريبية
نفّذ BEGIN TRANSACTION أو START TRANSACTION ثم ROLLBACK للتأكّد من تفعيل المعاملات التجريبية، ومن تفعيل ClickHouse Keeper أيضًا، إذ يُستخدم لتتبّع المعاملات.
BEGIN TRANSACTIONOk.ROLLBACKOk.أنشئ جدولًا للاختبار
CREATE TABLE mergetree_table
(
`n` Int64
)
ENGINE = MergeTree
ORDER BY nOk.ابدأ معاملة ثم أدرِج صفًا
BEGIN TRANSACTIONOk.INSERT INTO mergetree_table FORMAT Values (10)Ok.SELECT *
FROM mergetree_table┌──n─┐
│ 10 │
└────┘التراجع عن المعاملة، ثم الاستعلام من الجدول مرة أخرى
تحقّق من التراجع عن المعاملة:
ROLLBACKOk.SELECT *
FROM mergetree_tableOk.
0 rows in set. Elapsed: 0.002 sec.أتمّ المعاملة ثم استعلم من الجدول مرة أخرى
BEGIN TRANSACTIONOk.INSERT INTO mergetree_table FORMAT Values (42)Ok.COMMITOk. Elapsed: 0.002 sec.SELECT *
FROM mergetree_table┌──n─┐
│ 42 │
└────┘استقصاء المعاملات
يمكنك فحص المعاملات عبر الاستعلام عن جدول system.transactions، لكن انتبه إلى أنه لا يمكنك الاستعلام عن هذا
الجدول من جلسة ضمن معاملة. افتح جلسة clickhouse client ثانية للاستعلام عن هذا الجدول.
SELECT *
FROM system.transactions
FORMAT VerticalRow 1:
──────
tid: (33,61,'51e60bce-6b82-4732-9e1d-b40705ae9ab8')
tid_hash: 11240433987908122467
elapsed: 210.017820947
is_readonly: 1
state: RUNNINGمزيد من التفاصيل
راجع هذه التذكرة المرجعية للاطلاع على اختبارات أكثر شمولًا بكثير ومتابعة آخر المستجدات.