• 0
الغملاسي

الشموع الموقَدات لكشف تضارب البيانات

سؤال

( الشموع الموقــَدات لكشف تضارب البيانات )

السلام عليكم

في هذه المقالة سنتطرق لموضوع تضارب البيانات concurrency violation الغير واضح المعالم.

لماذا؟ السبب أن الحلول متعددة بحيث تعتمد على وضع و وقت و كيفية التضارب.

ناهيك عن تعدد أنواع التضارب , لذلك أوقدنا الشموع لرؤية هذا التضارب عن كثب.

هنالك على حسب علمي المتوضع ثلاثة وضعيات أو استراتيجيات لهذه المشكلة وهي كالتالي:

أولاً ما يعرف بـ استراتيجية التضارب المشؤوم pessimistic concurrency strategy.

ثانياً: ما يعرف بـ استراتجية التضارب المحمود optimistic concurrency strategy .

ثالثاً: ما يعرف بـ استراتيجية الاخر هو الاولى Last in wins strategy .

لكن قبل كل ذلك, ينبغي علينا تعريف مالمقصود بـتضارب البيانات.

هي عملية تحدث بين مستخدمين أو أكثر بحيث يقومان بالعمل على نفس البيانات في نفس الوقت

هذه العملية كما تعلمون تعرف بـ concurrency violation

متى يقع التضارب ؟

تقع المشكلة عند عملية التحديث سواءً في الاضافة أو التعديل او الحذف, لكن ليس في عملية الاختيار Select Statement

إلا ان عملية الاختيار, كما سيأتينا لاحقاً انها كذلك لم تسلم من عملية تضارب البيانات. وإن كان البرنامج يعمل كما ينبغي.

إلا ان المعطيات ستكون غير صحيحة.

هنالك تفسير إيجابي للتضارب وهو :

Maximize the amount of work that can be done by all users at the same time, and most

importantly, make all users feel like they’re important

الاستراتيجية الاولى : استراتيجية التضارب المشؤوم pessimistic concurrency strategy.

الوضع : ان يكون فقط مستخدم واحد يُحدث في نفس الوقت, وهذا المستخدم غير مشروط

ربما يكون عمر في المرة الاولى ويكون زيد في المرة الثانية. من يجلب البيانات أول هو احق بالتحديث عن سواه.

الاستراتيجية الاولى تعتمد على غلق الحقل الذي هو قيد الاستخدام كتحديث حتى ينتهي منه المستخدم الحالي

ثم بعد ذلك يفتح هذا الحقل للمستخدم الاخر. لكن لن يتم اعتماد تحديث المستخدم الاخر, هذه العملية تعرف بـالتحديث

المفقود a lost update.

على سبيل المثال زيد وعمر قاما بجلب بيانات عامود الراتب الشهري,

وكان الصف الاول فيه القيمة 5000 درهم,

تم قفل الحقل لمصلحة زيد, زيد زاد على الصف الاول 1000 درهم

الان البيانات لن تصل إلى عمر, وعمر ما زال ينتظر عملية جلب البيانات,

ولن يفلح, حتى يفرغ زيدٌ منها, الان قام زيد بالتحديث فاصبحت 6000 درهم.

تم فتح القفل عن الحقل, الان وصلت البيانات إلى عمر 6000 درهم .

عمر قام بانقاص 2000 درهم لتصبح 4000 درهم , قام عمر بتحديث البيانات.

لم يقبل التحديث لان التحديث المقفول بزيد لا يمكن تخطيه بتحديث عمر الغير مقفل في بداية الامر

حتى وان كان عمر من حدث فيما بعد. السبب كما ذكرنا أن هذه العملية تضمن تحديث واحد فقط في الوقت نفسه.

لذلك يعرف تحديث عمر بالتحديث المفقود lost update و الراتب الشهري في النهاية هو 6000 درهم .

ملاحظة: بما أن الحل متعلق بقفل الحقل, فهو واضح انه لا يدعم تقنية الاتصال المنقطع Disconnected environment

الاستراتيجية الثانية : استراتجية التضارب المحمود optimistic concurrency strategy .

الوضع : ان يكون اعتماد التحديث للبيانات متزامن مع الطرفين.

الاستراتيجية الثانية لا تعتمد على غلق الحقل, انما تعتمد على من يحدث اولاً قبل الاخرين.

لنفترض ان مستخدمان قاما بجلب البيانات و كانت قيمة الصف , عبارة عن حجز تذكرة

وباقي من كراسي الغير محجوزة 5 كراسي , قام المستخدم الاول بإعتماد الحجز له فاصبحت

4 وبما ان الحقل غير مقفل اثناء عمل المستخدم الاول عليه,

استطاع المستخدم الثاني جلب البيانات وهي 5 الان المستخدم الاخر قام بحجز كرسي له فاصبحت 4

قام بالتحديث , تم قبول التحديث ,الان قام المستخدم الاول ليحدث نفس الحقل بالقيمة 4

تم رفض التحديث كون القيمة العائدة هي القيمة الحالية وهي 4 كراسي فقط

و كذلك قيمة الصف القديمة ليست مطابقة للقيمة الاصلية في قاعدة البيانات والتي كانت 5 كراسي .

في الاخير, تم اعتماد حجزي المستخدمان مع ان الكراسي المحجوزة هو كرسي واحد فقط

بمعنى اخر تم حجز كرسي لشخصين...

متى يحدث التضارب المحمود : يحدث عندما يجلب مستخدم قيمة ما ويقوم الاخر

بجلب نفس القيمة ثم يغيرها ويحدثها , ثم يقوم الاول بمحاولة تحديث القيمة

التي تغيرت بواسطة المستخدم الاخر , هنا تقع المشكلة أو ما يعرف بـ optimistic concurrency violation

لماذا : لانه شرط هذه التقنية أن شرط التحديث يعتمد على التحقق من البيانات المُحدثة الحالية Current

مع البيانات الاصلية في قاعدة البيانات Original Data .

ملاحظة: الـ Dataset مصصمة لأجل هذه التقنية وهي داعمة لها و تتبناها.

الاستراتيجية الثالثة : استراتيجية الاخر هو الاولى Last in wins strategy .

الوضع : هو أن من يحدث أخرًا لا يفقد تحديثه.

الحل الثالث : لا يعتمد على غلق الحقل, انما يعتمد على من يحدث اخرًا بعد الاخرين.

لنفترض ان مستخدمان قاما بجلب البيانات و كانت قيمة الصف , عبارة عن حجز تذكرة

وباقي من كراسي الغير محجوزة 5 كراسي , قام المستخدم الاول بإعتماد الحجز له فاصبحت

4 وبما ان الحقل غير مقفل اثناء عمل المستخدم الاول عليه,

استطاع المستخدم الثاني جلب البيانات وهي 5 الان المستخدم الاخر قام بحجز كرسي له فاصبحت 4

قام بالتحديث , تم قبول التحديث ,الان قام المستخدم الاول ليحدث نفس الحقل بالقيمة 4

تم قبول التحديث وتم فقد قيمة تحديث المستخدم الاول وهي 4 كراسي فقط

تم اعتماد حجز المستخدم الاخر ,مع ضياع قيمة تحديث المستخدم الاول.

لماذا: لاسبب بسيط أن هذه التقنية لا تعتمد على تدقيق تطابق البيانات المُحدثة

بالبيانات الاصلية في قاعدة البيانات.

ملاحظة: اعتماد شرطية المفتاح الاساسي أو وقت التحديث أو رقم الصف, هي احدى حلول هذه الوضعية.

الحلول المطروحة: لمشكلة التضارب المشؤوم pessimistic concurrency strategy.

الحلول كثيرة باستخدام احدى عوازل العنصر transaction المتوفرة في النسخة 2005

لنتعرف على هذه الحلول بالتعرف على العوازل و انوعها.

مستوى العزل isolation level

ماهو مستوى العزل : هو عزل عملية التحديث الكلي transaction عن تحديث كلي أخر transaction

هنالك ثلاثة عوائق عند عملية التحديث الكلي وهم كالتالي :

اولاً : القراءة القذرة Dirty Read

ثانياً : القراءة المتعجلة non repeatable Read

ثالثًا : القراءة الوهمية phantom Read

القراءة القذرة Dirty Read تحدث هذه القراءة عندما يقوم مستخدمان أو اكثر, بالتعامل مع بيانات تم

رفض تحديثها عن طريق عملية التراجع عن التحديث Roll back عبر مستخدم ثالث.

على سبيل المثال: قام المستخدم الاول بتحويل 100 درهم من أموال الحساب الجاري وهي 500 درهم

إلى حساب التوفير الذي ليس به شيء,ومع ان حساب الجاري مقفل إلا ان المستخدم الاخر استطاع أن

يجلب قيمة الحساب الحالية وهي بعد التحول اصبحت 400 درهم, قام المستخدم الاول بعملية التحديث

إلا أن التحديث قد فشل , لسببٍ ما , على سبيل المثال حساب التوفير أغلق.. الان تمت عملية

التراجع Roll back أُعيدت المئة درهم لحساب الجاري و تم فتح القفل, لكن لازال المستخدم

الاخر يتعامل مع الراتب على اساس 400 درهم, لذلك هذا المنطق يعرف بالقراءة القذرة.

القراءة المتعجلة nonrepeatable Read تحدث عندما نقوم بقراءة بيانات تم تحديثها اثناء قرائتنا لها.

على سبيل المثال: قام المستخدم الاول بتشغيل تقرير الرواتب وكان حينها 1000 درهم للموظف الاول

في نفس الوقت كان مستخدم اخر يستخدم الحقول نفسها , حيث قام بزيادة راتب الموظف بـ 500 درهم

فبينما يفترض أن يكون راتب الموظف الاول هو 1500 درهم

إلا ان التقرير كان يعرض الراتب على اساس 1000 درهم فقط, لذلك يعرف هذا المنطق بالقراءة المتعجلة.

القراءة الوهمية phantom Read تحدث عندما نقوم بقراءة بيانات تم أضافة بيانات أخرى معها ولم ندركها.

على سبيل المثال: قام المستخدم الاول بتشغيل تقرير الرواتب وكان حينها 1000 درهم للموظف الاول

في نفس الوقت كان مستخدم اخر يستخدم الحقول نفسها , حيث قام بأضافة علاوة بدل الزوجية

بمبلغ 500 درهم , وبما أن العلاوة لم تكون حاضرة وقت تحميل التقرير

فهي قيمة مجهولة للمستخدم الاول , لذلك كان يفترض أن يكون المجموع في التقرير 1500 درهم

إلا ان التقرير كان يعرض الراتب على اساس 1000 درهم فقط, لذلك يعرف هذا المنطق بالقراءة الواهمة.

اي القراءة الغير صحيحة أو القراءة الظالمة.

الخيارات المتوفرة في مستوى العزل في SQL Server 2005

Chaos هذا الخيار غير مدعم في الـ SQLClient, ومدعم عبر الـ ADO.NET بشكل عام,

مثلاً في ADODB يعرف بـ adXactChaos , وهو عازل عنيد لايسمح بالكتابة على البيانات التي يتعامل معها.

ReadUncommitted هذا الخيار هو أقل مستوى للعزل (حيث تنطبق عليه المعوقات كلها)

وهو واضح من اسمه انه يقرء حتى القيمة التي لم تكون في الوضع Committed .

ReadCommitted: هذا الخيار الافتراضي ينتظر القيمة التي في وضع التعديل, حتى تصبح Committed

فيكمل المهمة أو يقوم بالتراجع. هذا الخيار لا يستطيع أن يعدل ما يتم تعديله من عنصر أخر,

بينما العناصر الاخرى تستطيع تعديل ما يعدله هذا الـ transaction

هذا العنصر يستخدم Row Versioning كإحدى الثوابت التي يعول عليها في عملياته.

الـ Row Version هو عبارة عن صف ينشأ في قاعدة البيانات tempdb كنوع من

الثوابت لمعرفة اخر حاله للصف قبل التعديل. يتم ذلك عبر specific transaction عنصر خاص يقوم

بعملية الربط بـ Link List بحيث تسند قيمة الصف في قاعدة البيانات الاصلية

بينما تسند نسخة الصف Version في قاعدة البيانات tempdb .

كذلك يستخدم الاقفال المشتركة shared locks لمنع القراءات القذرة ,لكن البيانات

يمكن تغيرها قبل ان ينتهي هو من مهامه , لذلك القراءة المتعجلة و الوهمية nonrepeatable & phantom reads,

احتمالية حدوثها واردة لا محالة.

ملاحظة: لإستخدام هذا النوع من العزل على قاعدة البيانات المعنية, نفذ هذا الكود.READ_COMMITTED_SNAPSHOT

RepeatableRead: هذا الخيار لا يستطيع أن يعدل قيمة لم يحن إعتمادها ولا يستطيع عنصر

اخر ان يعدل ما يتم تعديله في هذا العنصر الحالي, حتى ينتهي منها ويتم اعتمادها Committed .

هذا العنصر يستخدم الاقفال المشتركة shared locks وهذا يعني حماية البيانات المستخدمة من اي

طرف اخر, إلا للقراءة فقط, لكن المشكلة أنه يسمح كذلك بإضافة صفوف جديدة,

مما يسهم في مشكلة القراءة الوهمية Read phantom .

:Serializable هذا الخيار هو أعلى مستوى للعزل (حيث لا تنطبق عليه المعوقات كلها)

يُمنع هذا العزل من قراءة بيانات تستخدم من قبل الاخرين, وكذلك يمنع اي عنصر خارجي باستخدام

ما هو قيد التعديل عنده.حتى الاضافة يمنعها فلا يسمح بإخال صف جديد ضمن الصفوف التي لديه

حتى ينتهي منها. فهو عازل صارم للغاية.

Snapshot هذا الخيار يستخدم نسخة الصف كذلك Row Versioning في بدء عملياته,

هذا الخيار تُحجب عنه الصفوف التي يتم التعديل عليها من اطراف اخرى,فهو يرى فقط البيانات

التي لم تمس من قبل الاخرين. وهو لا يتطلب قفل الصفوف عند عملية القراءة ,إلا أنه يستخدمه

في عملية التراجع عن التعديل Rolled Back .

ملاحظة: لإستخدام هذا النوع من العزل على قاعدة البيانات المعنية , نفذ هذا الكود.

ALTER DATABASE Northwind
SET ALLOW_SNAPSHOT_ISOLATION ON
GO()

Unspecified غير محدد.

ملاحظة : العوازل الـ 6 مدعمة جميعها في الـ Compact framework

نصائح في استخدام العزل المناسب للمشاريع

العزل ReadUncommitted يفضل في المشاريع التي يتم التعامل مع البيانات بشكل سريع وفي اقصر وقت.

العزل RepeatableRead يفضل في المشاريع التي تتطلب دقة كاملة في تشغيل التحديثات التامة , مع ضمان منع

اي تحديث من اطراف اخرى, حتى ينته الحالي من عمليته الحالية.

العزل Serializable يفضل في المشاريع التي تتطلب دقة تامة عند التعامل مع البيانات , بحيث تمنع حتى عملية

الادخال من اطراف اخرى , حتى ينتهي الـ transaction من عمليته .

العزل Snapshot يفضل في المشاريع التي تستخدم محاسبات معقدة و لغرض القراءة فقط.

في الاخير وبلا ادنى شك أن هذا الفتات لا يغطي حقيقة تقنية العزل, إلا ان المقالة جرتنا للخوض فيه.

شاهد النصوص البرمجية لذلك.

' If no item of combobox selected
If Me.cboxIsoLevel.SelectedIndex < 0 Then
MsgBox("ComboBox is required in Pessimistic Strategy ")
Return
End If

' Create a connection object for datareader.
Using Cnn As New SqlConnection(My.Settings.NorthwindConnectionString)

' Open the connection object.
Cnn.Open()

' Note that you have to alter Northwind database
' Enable the Read Committed with Snapshots isolation level
' Script example...
' *******************************
' ALTER DATABASE Northwind
' SET ALLOW_SNAPSHOT_ISOLATION ON
' GO()
' *******************************

' Create local transaction.
Using transaction As SqlTransaction = _
Cnn.BeginTransaction(IsolationLevel.Snapshot)

' Create local command object.
Using cmd As New SqlCommand(Nothing, Cnn)

' Assign command transaction property
' To transaction object.
cmd.Transaction = transaction

Try

' Create query that update contactname
' Depend on ALFKI id.
Dim strCommand As String = _
"Update Customers SET ContactName = '" & txtPessimistic.Text & _
"' WHERE CustomerID = 'ALFKI'"

' Assign the query to command text property.
cmd.CommandText = strCommand

' Execute updates.
cmd.ExecuteNonQuery()

' Sleep for 10 seconds, for testing purposes.
Threading.Thread.Sleep(10000)

' Push(Data)
transaction.Commit()

' Clear dataset and refill it again.
FillData()

' Handling concurrency exception.
Catch ex As DBConcurrencyException
MsgBox(ex.Message)

' Handling others exception.
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Using

' Implicitly disposes (closes) connection,
'and rolls back transaction (if not already committed).
End Using
End Using
End Sub

الحلول المطروحة: لمشكلة التضارب المحمود optimistic concurrency strategy.

الحل الاول : استخدام الحدث RowUpdated Event التابعة للـ DataAdpater بهي نستطيع أن

نعرف هل حدث التصادم أم لا و ببعض خصائصه نتحكم بالخطأ الذي صدر من صفٍ ما .

الحل الثاني: هو تمكين الخاصية ContinueUpdateOnError بحيث تساوي True لتكملة التحديث حتى وان كان

هنالك خطأٌ ما في صفٍ ما, بحيث يقوم بتخطي الخطأ دون تحديثه, مع استمرار تحديث الصفوف التي بعده.

هذه الخاصية : تمنع إنهيار أو تجمد البرنامج , وكذلك تمنع رسالة الخطأ الافتراضية .

الخاصية ContinueUpdateOnError هي احدى خواص الـ DataAdapter .

ثالثاً : يمكنك امساك التضارب عبر القالب

DBConcurrencyException

شاهد النصوص البرمجية لعمل ذلك.

نكتب هذا الكود في صفحة الـ DataSet.vb

Imports System.

Handling_Database_Operation_Conflicts.rar

تم تعديل بواسطه الشهاب الحارق
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

29 إجابة على هذا السؤال .

  • 0

يا سلام أستاذي الكريم نورت علينا بعض الأمور ..

بصراحة كنت بصدد دراسة الموضوع من ناحية الـ SQL Server

درسك الجميل كمّل بعض تساؤلاتي التي لم أجد حلاً لها في SQL Server بعد عدد كبير من التجارب

التي كنت أقوم بها أثناء تعمقي في موضوع الـ Transaction ..

شكراً مرة أخرى .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

حل المشكلة التي كنت أتحدث عنها ولم أحصل على جوابها في هذه المشاركه ( لسبب عدم فهم الاخوان جزاهم الله خير لما أريد ) ..

	Private Sub MyDA_RowUpdated(ByVal sender As Object, ByVal e As System.Data.OleDb.OleDbRowUpdatedEventArgs) Handles MyDA.RowUpdated
' هذا الحدث من اجل الحصول على رقم أخر سجل اضيف وله خاصية الترقيم التلقائي
Try
If e.Status = UpdateStatus.Continue AndAlso e.StatementType = StatementType.Insert Then
'Get NewID
Dim cmdGetIdentity As New OleDbCommand("SELECT @@IDENTITY", MyConnection)
cmdGetIdentity.CommandType = CommandType.Text
e.Row("ID") = Int32.Parse(cmdGetIdentity.ExecuteScalar().ToString())
e.Row.AcceptChanges()
'MsgBox(e.Row("ID"))
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "الحصول على رقم أخر سجل اضيف", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.RtlReading, False)
End Try
End Sub

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بســم الله الـرحمــن الرحيــم

السلام عليكــم ورحمـة الله وبركاتــه

جزاك الله خير

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الموضوع هام جدا ومشوق أخي الكريم لكن لابد من وجود حل لما لا يعتمد في رأي الشخصي ولست ممن يقترح لعدم خبرتي ، لما للا يعتمد على التحديث المباشر للداتاسيت بعد كل عملية أو القيام بجرد كل التحديثات فيحين يتم قفل الحقول إعادة فتحها نباشرة بعد الإنتهاء من كل عملية تحديث

والله أعلم

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .