4 دقیقه میانگین مدت زمان مطالعه است

شروع

سیستم بورس اطلاعات رو در بستر Socket به کارگزارها ارسال میکنه
یکی از این اطلاعات که مقدار ریت بالایی هم داره، سرخط های بازار هست که افراد معمولی فقط 5 تا عنوان اون رو در دو سمت خرید و فروش میتونن مشاهده کنن
اما افراد معامله گر امکان مشاهده کامل این جدول رو که قیمت و مقدار حجم خرید رو در دو سمت خرید و فروش نشون میده، دارن

مشکل

همونطور که گفتم مقدار دیتا زیادی در مدت زمان خیلی کم ارسال میشه
بطور مثال گفته میشه که از سرخطها سفارشی که 100 عدد از یه نماد خاص و در این حجم بود حذف/ویرایش شد
روشی که قبلا استفاده میشد ، آپدیت کردن این سطرها داخل دیتابیس بود ولی چون دستور update زمان زیادتری نسبت به دستور insert میگیره، این سیستم کند بود
کند بودن هم در بورس که افراد سر ثانیه با هم دیگه رقابت میکنن اصلا خوب نیست

راه حل

راه حلی که به ذهنمون رسید، تغییر پردازش داده ها بصورتی بود که فقط عملیات insert انجام بشه
یعنی برای دستورهای delete و update هم یه سطر جدید داخل دیتابیس باشه
برای این کار ساختار جدول تغییر کرد و دیگه نمیشد از کلید primary که قبلا تعریف شده بود استفاده کرد
چون دیگه سه مقداری که قبلا کلید رو تشکیل میدادن دیگه مقدار یونیک نداشتن
تغییرات این قسمت خودش زیاد بود و چیزی که داخل این پست میخوام بگم خیلی ربطی به اون نداره
خلاصه کار انجام شد و بعد تست هم منتشر شد. همه چی داشت خوب پیش میرفت که کمکم تیکت ها شروع شد
همه هم میگفتن که این سرخط ها درست نشون داده نمیشه، یعنی یه قسمت برنامه که طبق اطلاعات دیگه ای محل افراد رو داخل معامله نشون میداد یه عدد و این قسمت جدید یه مقدار دیگه که بیشتر بود رو نشون میداد

جستجو

شروع کردیم به تست دوباره و شبیه سازی بازار واقعی در سیستم خودمون
حتی سطرهای دیتابیس رو برای یک روز بصورت تک تک نگاه کردیم تا ببینیم مشکل از کجاست
ظاهرا همه چی درست کار میکرد. پس بیشتر فکر کردیم
برای insert کردن از bulk استفاده میکردیم، طبق جستجویی که کردم دونستم تو این حالت اگه کمتر از 10 عدد به خطا بخورن عملیات bulk انجام میشه و خطایی هم داده نمیشه
پس برای بررسی این مورد از کد زیر استفاده کردم تا بببینم این حالت پیش میاد یا نه

var filesInserted = 0L;
bulkCopy.NotifyAfter = dataTable.Rows.Count;
bulkCopy.SqlRowsCopied += (s, e) => filesInserted = e.RowsCopied;

اما این مشکل اصلا پیش نیومده بود
شروع کردم به خوندن لاگ های ذخیره شده تا ببینم اصلا اروی در برنامه بوجود اومده یا نه
اما باز هم به در بسته خودرم، هیچ خطایی در چند ماه گذشته پیش نیومده بود
کدهای نوشته شده توسط خودم و بقیه بصورت چندباره و خط به خط خونده شد ولی هیچ مشکلی نبود
کم کم صدای مدیران بالایی هم داشت درمیومد که چرا این قسمت درست کار نمیکنه و اوضاع داشت خطرناک میشد
پس بیشتر جستجو کردیم تا ببینیم این مشکل دقیقا در چه زمانی پیش میاد
طبق بررسی ها مشخص شد که این مشکل فقط در سمت فروش پیش میاد. همچنین فقط ساعت 9 صبح
کم کم داشتیم به جاهای خوبی میرسیدیم

موفقیت

شروع کردیم به مطالعه پیام هایی که در این زمان خاص میاد
بورس در شروع معاملات پیامی ارسال میکنه که میگه تمام سفارشات کمتر از مبلغ x رو حذف کن
در ورژن قبلی و این ورژن جدید این قسمت تغییر خاصی نکرده بود و در هر صورت تمام سطرهایی که مبلغ کمتر از x داشتن حذف میشدن
چون برخلاف حذف یه سرخط نمیشد دقیق دونست که کدوم سطرها باید حذف بشن و همچنین اگه میخواستیم بررسی هم کنیم خودش سیستم رو کند میکرد
مهمتر از همه اینکه این پیام فقط یک بار در روز ارسال میشه، پس به همون صورت قبل باقی موند

مشکل هم دقیقا همین قسمت بود
شرطی که بررسی میشد این بود که تموم اونهایی که مبلغ کمتر از x دارن حذف بشن

DELETE  FROM dbo.[Order]
        WHERE   
                Side = @side
                AND Price < @price

این در حالت قبلی برنامه به درستی کار میکرد، ولی نکته ای که در سیستم جدید حواس ما بهش نبود، insert کردن بجای delete تک رکورد بود
برای این کار سطر جدیدی که همون مشخصات سطر قبل رو داشت ولی مبلغش برابر 0 بود رو به دیتابیس اضافه میکردیم
مشکل هم دقیقا از این مورد بود
شرطی که برای حذف تموم رکوردها که بالاتر بود، سطرهایی که مبلغ 0 داشتن رو هم حذف میکرد
پس سفارشاتی که قبلا حذف شده بودن و نباید در محاسبه میومدن هم دوباره برمیگشتن
بصورت مثلا یه سفارش با مبلغ 2000 و حجم 200 بوده
این سفارش در صورت حذف یه رکورد جدید براش با حجم 200 و مبلغ 0 اضافه میشد
کوئری بالا این سطر دوم رو پاک میکرد و سطر اول دوباره زنده میشد و داخل محاسبات میومد

دلیل اینکه فقط در سمت خرید بود هم این هست که سمت خرید باید بصورت دیگه ای عمل میکردیم و سطرهایی که مبلغ بیشتر از سطر ما داشتن رو حذف میکردیم
یعنی داخل کوئری بالا شرط price عوض میشد
پس حالت حذف کردن مبلغ 0 اصلا پیش نمیومد

در نهایت کوئری به صورت زیر تغییر کرد

DELETE  FROM dbo.[Order]
        WHERE   
                Side = @side
                AND Price > 0
                AND Price < @price

یک شرط کوچیک که باعث اون همه مشکل شده بود !!!

تگ ها: , ,

دسته بندی ها:

به روز شده در: