মাইএসকিউএল: একটি লেনদেন সারি লক হবে?


13

আমি এর আগে মাইএসকিউএল লেনদেন ব্যবহার করার চেষ্টা করিনি, আমি কেবল কিছু স্পষ্ট করতে চাই।

যদি দু'জন ব্যবহারকারী খুব সঠিক সময়ে একটি ক্যোয়ারী চালায় তবে মাইএসকিউএল এটি কীভাবে পরিচালনা করবে? যেমন ব্যবহারকারীরা একটি রেকর্ড আপডেট করার চেষ্টা করছে।

ইউজার 1: আপডেট টেবিল সেট কলাম = কলাম - 4 যেখানে কলাম_আইডি = 1;

ইউজার 2: আপডেট টেবিল সেট কলাম = কলাম - 7 যেখানে কলাম_আইডি = 1;

এখন আমি যদি লেনদেন ব্যবহার করি তবে মাইএসকিউএল চয়ন করবে যে কোন কোয়েরিটি প্রথম কার্যকর করা হবে এবং প্রথম অনুসন্ধানটি করা না হওয়া অবধি দ্বিতীয় ব্যবহারকারীকে লক করা হবে? এটি একটি টেবিল লক বা একটি সারি লক হবে?

তৃতীয় ব্যবহারকারী যদি একটি নির্বাচিত বিবৃতি প্রদান করবেন? মাইএসকিউএল ফিরে আসবে এমন মান কী হবে?

পিএস এটি ইনোডবিতে থাকবে।

উত্তর:


17

এর মতো একটি একক বিবৃতি মাইআইএসএএম বা ইনোডিবিতে, লেনদেনের সাথে বা স্বতঃআপনার সাথে = একই কাজ করে। এটি ক্যোয়ারী করার জন্য যথেষ্ট ব্লক করে, যার ফলে অন্য সংযোগটি অবরুদ্ধ করে। শেষ হয়ে গেলে, অন্যান্য সংযোগটি এগিয়ে যায়। সমস্ত ক্ষেত্রে, কলামটি শীঘ্রই 11 দ্বারা হ্রাস পেয়েছে।

তৃতীয় ব্যবহারকারীর মান 0 বা 4 বা 7 বা 11 দ্বারা হ্রাস হতে পারে "খুব সঠিক সময়" সত্যই সম্ভব নয় কারণ, প্রতিটি বিবৃতি কার্যকর করার সময় কোনও একক থ্রেডযুক্ত লকটি চেক / সেট / যাই হোক না কেন । এটি হ'ল এগুলি সিরিয়ালিয়াল করা হবে , এটি এত দ্রুত যে আপনি এটি দেখতে পারবেন না।

InnoDB কেবল সারি লক করে, টেবিলগুলি নয়। (ঠিক আছে, ডিডিএল বিবৃতিটি সাহসী লকগুলি করে))

আরও আকর্ষণীয় হয়ে ওঠে তা হ'ল একটি লেনদেন যা দুটি জিনিসকে সংশোধন করে, বা এটি লক্ষণীয় পরিমাণ সময় নেয়:

ইন্টেন্টেশন কেস: একক আইটেম কিন্তু সময় নিচ্ছে:

BEGIN;
SELECT something;
think about it for a while
UPDATE that something;
COMMIT;

নির্বাচনগুলি এইভাবে লেখা দরকার:

SELECT something  FOR UPDATE;

এটি অন্যান্য সংযোগগুলিকে বলছে "আমি সারিটি আপডেট করার ইচ্ছা করি; দয়া করে আমাকে গোলমাল করবেন না"। (আমি এই উদাহরণটি সামনে এনেছি, কারণ অনেকগুলি নবজাতক এই সূক্ষ্মতা মিস করে))

ডেডলক কেস: 2 টি জিনিস দিয়ে মেস করা:

BEGIN;    -- in one connection
UPDATE thing_1;
UPDATE thing_2;
COMMIT;

BEGIN;    -- in another connection, at the "exact same time"
UPDATE thing_2;
UPDATE thing_1;
COMMIT;

এটি অচলতার সর্বোত্তম উদাহরণ - প্রত্যেকটি একটি জিনিস ধরে এবং তারপরে অন্য জিনিসটির কাছে পৌঁছায়। স্পষ্টতই এটি কাজ করা যাবে না। একটি লেনদেন নিহত হয়; অন্য সম্পূর্ণ। অতএব, আপনার অবশ্যই ত্রুটিগুলি পরীক্ষা করা উচিত , যাতে আপনি এটি আবিষ্কার করতে পারেন।

অচলাবস্থার স্বাভাবিক প্রতিক্রিয়া হ'ল পুরো ব্যর্থ লেনদেনের পুনরায় খেলানো। ততক্ষণে অন্য সংযোগটি হস্তক্ষেপ করবে না এবং সমস্যা ছাড়াই এটি এগিয়ে যাওয়া উচিত। (ঠিক আছে, অন্য কোনও সংযোগ আরেকটি অচলাবস্থা তৈরি করতে পারে))

বিলম্বের কেস: যদি দুটি সংযোগ একই ক্রমে একাধিক জিনিস দখল করে , তবে অন্যটি শেষ না হওয়া পর্যন্ত একটি বিলম্ব হতে পারে। এটি "চিরকাল অপেক্ষা করা" থেকে বাঁচতে একটি ডিফল্ট 50-সেকেন্ড রয়েছে innodb_lock_wait_timeout। আপনার সহজ জুটি UPDATEsআসলে এই ক্ষেত্রে একটি উদাহরণ। একটি অবিলম্বে শেষ হবে; প্রথমটি শেষ না হওয়া পর্যন্ত অন্যটি স্থবির হয়ে পড়ে।

আপনার স্পর্শের জিনিসগুলি ধারাবাহিকভাবে অর্ডার করে কীভাবে কোনও ডেডলক (কিছু ক্ষেত্রে) বিলম্বে পরিণত হতে পারে তা নোট করুন।

অটোকোমিট = 1: এই সেটিংটি সহ এবং কল না করে BEGIN, প্রতিটি বিবৃতি কার্যকরভাবে:

BEGIN;
your statement
COMMIT;

অটোকোমিট = 0: এটি হওয়ার জন্য অপেক্ষা করা সমস্যা। আপনি যখন একটি রচনা কোয়েরি সম্পাদন করেন, তখন একটি BEGINস্পষ্টভাবে উত্পন্ন হয়। যাইহোক, এটা অবশেষে সমস্যাটি আপনার দায়িত্ব COMMIT। যদি আপনি এটি করতে ব্যর্থ হন তবে আপনি অবাক হবেন কেন আপনার সিস্টেমটি স্তব্ধ হয়ে আছে। (আর একটি সাধারণ নবাগত বাগ।) আমার পরামর্শ: "কখনও ব্যবহার করবেন না =0"।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.