কখন আপডেট… আপডেটের জন্য ব্যবহার করবেন?


119

পিছনে ব্যবহারের কেসটি বুঝতে আমাকে সহায়তা করুন SELECT ... FOR UPDATE

প্রশ্ন 1 : নিম্নলিখিত কখন SELECT ... FOR UPDATEব্যবহার করা উচিত তার একটি ভাল উদাহরণ ?

প্রদত্ত:

  • রুম [ID]
  • ট্যাগস [আইডি, নাম]
  • রুম_ট্যাগগুলি [রুম_আইডি, ট্যাগ_আইডি]
    • রুম_আইডি এবং ট্যাগ_আইডি বিদেশী কী

অ্যাপ্লিকেশনটি সমস্ত কক্ষ এবং তাদের ট্যাগগুলি তালিকাবদ্ধ করতে চায়, তবে অপসারণ করা ঘরগুলির তুলনায় কোনও ট্যাগ নেই এমন কক্ষের মধ্যে পার্থক্য করা দরকার। যদি নির্বাচনের জন্য ... আপডেটের জন্য ব্যবহার না করা হয়, তবে যা ঘটতে পারে তা হ'ল:

  • প্রাথমিকভাবে:
    • কক্ষ রয়েছে [id = 1]
    • ট্যাগ রয়েছে [id = 1, name = 'cats']
    • রুম_ট্যাগগুলিতে রয়েছে [room_id = 1, tag_id = 1]
  • থ্রেড 1: SELECT id FROM rooms;
    • returns [id = 1]
  • থ্রেড 2: DELETE FROM room_tags WHERE room_id = 1;
  • থ্রেড 2: DELETE FROM rooms WHERE id = 1;
  • থ্রেড 2: [লেনদেন কমিট করে]
  • থ্রেড 1: SELECT tags.name FROM room_tags, tags WHERE room_tags.tag_id = 1 AND tags.id = room_tags.tag_id;
    • একটি খালি তালিকা ফেরত দেয়

এখন থ্রেড 1 মনে করে যে রুম 1 এর কোনও ট্যাগ নেই, তবে বাস্তবে ঘরটি সরানো হয়েছে। এই সমস্যাটি সমাধান করার জন্য, থ্রেড 1 টি হওয়া উচিত SELECT id FROM rooms FOR UPDATE, যার ফলে থ্রেড 2টি roomsথ্রেড 1 সম্পন্ন হওয়া থেকে মুছে ফেলা থেকে আটকাতে হবে। এটা কি ঠিক?

প্রশ্ন 2 : যখন এক ব্যবহার করা উচিত SERIALIZABLEবনাম লেনদেন বিচ্ছিন্নতা READ_COMMITTEDসঙ্গে SELECT ... FOR UPDATE?

উত্তরগুলি বহনযোগ্য হতে পারে (ডাটাবেস-নির্দিষ্ট নয়)। যদি এটি সম্ভব না হয় তবে দয়া করে কেন তা ব্যাখ্যা করুন।


2
আপনি কোন আরডিবিএমএস ব্যবহার করছেন?
কাসনসুই

2
@ কোসনোই, প্রশ্নের নীচে উল্লিখিত হিসাবে, আমি একটি পোর্টেবল (ডাটাবেস-নির্দিষ্ট নয়) সমাধান খুঁজছি।
গিলি

2
বিকল্পগুলি REPEATABLE_READএবং READ_COMMITTEDএমনকি পোর্টেবল বিকল্পগুলি কি?
এগুলির

3
@ বিলিওনিল: নোট করুন যে বিচ্ছিন্নতা মোডগুলি গ্যারান্টি দেয় যে আপনি যে quirks তারা অনুমতি দিচ্ছেন না তা দেখেন না, তবে তারা যে ভঙ্গিগুলি অনুমতি দেয় তা সম্পর্কে কিছুই বলেন না। এর অর্থ হ'ল সেটিংস, বলুন, READ COMMITTEDমোডটি আপনাকে অন্য কোনও লেনদেনের দ্বারা প্রতিশ্রুতিবদ্ধ রেকর্ডগুলি দেখতে পাবে কিনা তা নির্ধারণ করে না: এটি কেবলমাত্র নিশ্চিত করে যে আপনি কখনই অনিবন্ধিত রেকর্ড দেখতে পাবেন না।
কাসনসুই

3
একটি select ... for updateঅন roomsএখনও room_tagsমুছতে অনুমতি দেবে কারণ সেগুলি পৃথক সারণী। আপনি কি জিজ্ঞাসার অর্থ কি এই for updateধারাটি থেকে মুছে ফেলা রোধ করবে rooms?
ক্রিস

উত্তর:


84

ঘর এবং ট্যাগগুলির মধ্যে ধারাবাহিকতা অর্জনের এবং কক্ষগুলি মুছে ফেলার পরে আর কখনও ফিরে আসবে না তা নিশ্চিত করার একমাত্র পোর্টেবল উপায় সেগুলি লক করে রাখা SELECT FOR UPDATE

তবে কিছু সিস্টেমে লক করা সামঞ্জস্য নিয়ন্ত্রণের একটি পার্শ্ব প্রতিক্রিয়া এবং আপনি FOR UPDATEস্পষ্টভাবে উল্লেখ না করে একই ফলাফল অর্জন করেন ।


এই সমস্যাটি সমাধান করার জন্য, থ্রেড 1 টি হওয়া উচিত SELECT id FROM rooms FOR UPDATE, যার ফলে থ্রেড 2টি roomsথ্রেড 1 সম্পন্ন হওয়া থেকে মুছে ফেলা থেকে আটকাতে হবে। এটা কি ঠিক?

এটি আপনার ডাটাবেস সিস্টেমটি ব্যবহার করছে এমন একচ্ছত্র নিয়ন্ত্রণের উপর নির্ভর করে।

  • MyISAMইন MySQL(এবং অন্যান্য বেশ কয়েকটি পুরানো সিস্টেম) কোনও প্রশ্নের সময়কালের জন্য পুরো টেবিলটিকে লক করে।

  • ইন SQL Server, SELECTকোয়েরিগুলি তাদের পরীক্ষিত রেকর্ড / পৃষ্ঠাগুলি / সারণীতে ভাগ করা লকগুলি রাখে, এবং DMLক্যোয়ারীগুলি আপডেট লকগুলি রাখে (যা পরে একচেটিয়া হিসাবে প্রচারিত হয় বা ভাগ করা লকগুলিতে ডমোট হয়)। এক্সক্লুসিভ লকগুলি ভাগ করা লকগুলির সাথে বেমানান, সুতরাং অন্য সেশন শুরু না হওয়া পর্যন্ত হয় SELECTবা DELETEকোয়েরি লক হবে will

  • ডাটাবেস যা ব্যবহার MVCC(যেমন Oracle, PostgreSQL, MySQLসঙ্গে InnoDB), একটি DMLকোয়েরি রেকর্ডের একটি অনুলিপি (এক বা অন্য উপায়) তৈরি করে এবং সাধারণত পাঠকদের বিপরীতভাবে লেখক ও ভাইস ব্লক না। এই ডেটাবেসগুলির জন্য, একটি SELECT FOR UPDATEকাজে আসবে: এটি অন্য কোনও অধিবেশন ঠিক না হওয়া অবধি লক করবে SELECTবা DELETEকোয়েরিটি লক করবে SQL Server

যখন কারও সাথে REPEATABLE_READলেনদেনের বিচ্ছিন্নতা ব্যবহার করা উচিত ?READ_COMMITTEDSELECT ... FOR UPDATE

সাধারণত, REPEATABLE READভুত সারিগুলি নিষিদ্ধ করে না (সারিগুলি পরিবর্তিত হওয়ার পরিবর্তে অন্য লেনদেনে হাজির বা অদৃশ্য হয়ে গেছে)

  • ইন Oracleএবং তার আগে PostgreSQLসংস্করণ REPEATABLE READআসলে জন্য একটি প্রতিশব্দ হয় SERIALIZABLE। মূলত, এর অর্থ হ'ল লেনদেন শুরু হওয়ার পরে পরিবর্তনগুলি দেখতে পাবে না। সুতরাং এই সেটআপে, সর্বশেষ Thread 1ক্যোয়ারীটি রুমটি এমনভাবে ফিরিয়ে দেবে যেন এটি কখনও মোছা হয়নি (যা আপনি যা চেয়েছিলেন তা হতে পারে বা নাও পারে)। ঘরগুলি মোছার পরে আপনি যদি সেগুলি দেখাতে না চান তবে আপনার সারিগুলি লক করে দেওয়া উচিতSELECT FOR UPDATE

  • ইন InnoDB, REPEATABLE READএবং SERIALIZABLEপাঠকদের: ভিন্ন জিনিস SERIALIZABLEমোড সেট রেকর্ড তারা মূল্যায়ন পরবর্তী কী কেশ, কার্যকরীভাবে সমবর্তী প্রতিরোধ DMLতাদের উপর। সুতরাং আপনার SELECT FOR UPDATEসিরিয়ালাইজযোগ্য মোডে প্রয়োজন হবে না , তবে এগুলিতে REPEATABLE READবা এর দরকার নেই READ COMMITED

নোট করুন যে বিচ্ছিন্নতা মোডের মানটি আপনাকে নির্দেশ দেয় যে আপনি আপনার অনুসন্ধানগুলিতে কিছু স্ফূর্তি দেখতে পাচ্ছেন না তবে কীভাবে (লকিং সহ MVCCবা অন্য কোনওভাবে) সংজ্ঞায়িত করেন না ।

যখন আমি বলি " SELECT FOR UPDATEনির্দিষ্ট ডেটাবেস ইঞ্জিন বাস্তবায়নের পার্শ্ব প্রতিক্রিয়াগুলির কারণে" আপনার "আমার আসলেই যোগ করা উচিত ছিল না "।


1
সর্বশেষ পয়েন্টটি বিষয়টির জটিলতা, আমি মনে করি: "আপনাকে সিরিয়ালাইজযোগ্য মোডে একটি নির্বাচন বাছাইয়ের দরকার নেই, তবে তাদের পুনরাবৃত্তিযোগ্য পড়ুন বা পড়ুন কমিট করা দরকার"।
কলিন 'হার্ট

তুমি ঠিক বলছো. দ্বিতীয় প্রশ্নটি জিজ্ঞাসা করা SERIALIZABLEউচিত ছিল কখন এর READ_COMMITTEDসাথে বনাম ব্যবহার করা উচিত SELECT ... FOR UPDATE। এই আপডেট হওয়া প্রশ্নটি প্রতিবিম্বিত করতে দয়া করে আপনার উত্তরটি আপডেট করতে পারেন?
গিলি

1
@ গিলি: "আপনার SELECT FOR UPDATEসিরিয়ালাইজেবল মোডে দরকার নেই", সাথে InnoDB। অন্যান্য MVCCসিস্টেমগুলির সাথে, দুটি হ'ল প্রতিশব্দ এবং আপনার প্রয়োজন SELECT FOR UPDATE
কাসনসুই

1
আমি কলিনের পোস্টটি আমার নির্দিষ্ট প্রশ্নের উত্তরগুলি আপনার উত্তরের চেয়ে ভাল পেয়েছি তবে আপনি প্রদত্ত সমস্ত রেফারেন্সের জন্য আমি প্রশংসা করি। আমি এমন একটি উত্তর গ্রহণ করব যা সর্বোত্তম দুটিটির সংমিশ্রণ করবে (উপরে সুনির্দিষ্ট উত্তরগুলি, নীচে নীচের উল্লেখগুলি সমর্থন করে)
গিলি

This depends on the concurrency control your database system is using: আমি মনে করি আপনি চুল বিভক্ত করছেন। আপনি নীচে তালিকাভুক্ত সমস্ত ক্ষেত্রে বলা হয়েছে যে SELECTলেনদেনের শেষের মধ্যে ঘরটি মুছে ফেলা হয় না । সুতরাং, উত্তরটি নীচে কেবল Yesসমর্থনকারী রেফারেন্সগুলির সাথে হওয়া উচিত নয় ?
গিলি

33

ছোট উত্তর:

প্রশ্ন 1: হ্যাঁ।

প্রশ্ন 2: আপনি যা ব্যবহার করেন তা বিবেচ্য নয়।

দীর্ঘ উত্তর:

একটি select ... for update(যেমন বোঝা) নির্দিষ্ট সারি নির্বাচন করব কিন্তু যদি তারা ইতিমধ্যেই বর্তমান লেনদেনের (অথবা যেন পরিচয় আপডেট সঞ্চালিত হয়েছে) দ্বারা আপডেট করা হয়েছে তাদের লক। এটি আপনাকে বর্তমান লেনদেনে আবার এগুলি আপডেট করার অনুমতি দেয় এবং তারপরে অন্য কোনও লেনদেন ছাড়াই কোনওভাবে এই সারিগুলিকে সংশোধন করতে সক্ষম হয় commit

এটি দেখার আরও একটি উপায়, এটি যেন নিম্নলিখিত দুটি বিবৃতিটিকে পরমাণুভাবে কার্যকর করা হয়:

select * from my_table where my_condition;

update my_table set my_column = my_column where my_condition;

যেহেতু আক্রান্ত সারিগুলি my_conditionলক করা আছে, অন্য কোনও লেনদেন সেগুলি কোনওভাবেই সংশোধন করতে পারে না এবং তাই, লেনদেনের বিচ্ছিন্নতা স্তরটি এখানে কোনও পার্থক্য করে না।

আরও লক্ষ করুন যে লেনদেনের বিচ্ছিন্নতা স্তরটি লক করা থেকে স্বতন্ত্র: একটি পৃথক বিচ্ছিন্ন স্তর নির্ধারণ করা আপনাকে লেনদেনের আশেপাশে পেতে এবং আপনার লেনদেনের দ্বারা লক হওয়া আলাদা লেনদেনে সারিগুলি আপডেট করার অনুমতি দেয় না।

লেনদেনের অগ্রগতি চলাকালীন লেনদেনের বিচ্ছিন্নতা স্তরগুলি (বিভিন্ন স্তরে) গ্যারান্টি দেয় তা হ'ল ডেটার সামঞ্জস্য।


1
আমি মনে করি What transaction isolation levels do guarantee [...] is the consistency of data once transactions are completed.ভুলভাবে বোঝায় যে লেনদেনের সময় কী ঘটে তা বিচ্ছিন্নতা স্তরগুলি প্রভাবিত করে না । আমি এই বিভাগটি সংশোধন করে এবং কোনও লেনদেনের সময় আপনি কী দেখেন (বা দেখেন না) সেগুলি কীভাবে প্রভাবিত করে সে সম্পর্কে আরও বিশদ সরবরাহ করার পরামর্শ দিচ্ছি।
গিলি

1
আমি আপনার পোস্টটি আমার সুনির্দিষ্ট প্রশ্নের উত্তর কাসনোইয়ের চেয়ে ভাল পেয়েছি তবে আমি তার সরবরাহিত সমস্ত রেফারেন্সের প্রশংসা করি। আমি এমন একটি উত্তর গ্রহণ করব যা সর্বোত্তম দুটিটির সংমিশ্রণ করবে (উপরে সুনির্দিষ্ট উত্তরগুলি, নীচে নীচের উল্লেখগুলি সমর্থন করে)
গিলি

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