কোন পরিস্থিতিতে একটি স্কিল সংযোগ স্বয়ংক্রিয়ভাবে একটি পরিবেশনার ট্রান্সজেকশনস্কোপ লেনদেনের তালিকাভুক্ত?


201

কোনও লেনদেনে কোনও স্কেল সংযোগের জন্য "তালিকাভুক্ত" হওয়ার অর্থ কী? এর সহজ অর্থ কি এই যে আমি সংযোগে চালিত আদেশগুলি লেনদেনে অংশ নেবে?

যদি তা হয় তবে কোন পরিস্থিতিতে কোনও এসকিএলসিঙ্কেশন স্বয়ংক্রিয়ভাবে একটি পরিবেশনার ট্রানজেকশনস্কোপ লেনদেনে তালিকাভুক্ত হবে?

কোড মন্তব্যে প্রশ্নগুলি দেখুন। প্রতিটি প্রশ্নের উত্তরে আমার অনুমানক প্রথম প্রশ্নটি প্রথম বন্ধনীতে অনুসরণ করে।

দৃশ্য 1: সংযোগ খোলা একটি লেনদেনের সুযোগ ভিতরে

using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = ConnectToDB())
{   
    // Q1: Is connection automatically enlisted in transaction? (Yes?)
    //
    // Q2: If I open (and run commands on) a second connection now,
    // with an identical connection string,
    // what, if any, is the relationship of this second connection to the first?
    //
    // Q3: Will this second connection's automatic enlistment
    // in the current transaction scope cause the transaction to be
    // escalated to a distributed transaction? (Yes?)
}

পরিস্থিতি 2: সংযোগগুলি ব্যবহার করে একটি লেনদেনের সুযোগের বাইরে এটি খোলা হয়েছিল

//Assume no ambient transaction active now
SqlConnection new_or_existing_connection = ConnectToDB(); //or passed in as method parameter
using (TransactionScope scope = new TransactionScope())
{
    // Connection was opened before transaction scope was created
    // Q4: If I start executing commands on the connection now,
    // will it automatically become enlisted in the current transaction scope? (No?)
    //
    // Q5: If not enlisted, will commands I execute on the connection now
    // participate in the ambient transaction? (No?)
    //
    // Q6: If commands on this connection are
    // not participating in the current transaction, will they be committed
    // even if rollback the current transaction scope? (Yes?)
    //
    // If my thoughts are correct, all of the above is disturbing,
    // because it would look like I'm executing commands
    // in a transaction scope, when in fact I'm not at all, 
    // until I do the following...
    //
    // Now enlisting existing connection in current transaction
    conn.EnlistTransaction( Transaction.Current );
    //
    // Q7: Does the above method explicitly enlist the pre-existing connection
    // in the current ambient transaction, so that commands I
    // execute on the connection now participate in the
    // ambient transaction? (Yes?)
    //
    // Q8: If the existing connection was already enlisted in a transaction
    // when I called the above method, what would happen?  Might an error be thrown? (Probably?)
    //
    // Q9: If the existing connection was already enlisted in a transaction
    // and I did NOT call the above method to enlist it, would any commands
    // I execute on it participate in it's existing transaction rather than
    // the current transaction scope. (Yes?)
}

উত্তর:


188

এই প্রশ্নটি জিজ্ঞাসা করার পর থেকে আমি কিছু পরীক্ষা করেছি এবং আমার নিজের থেকে সমস্ত উত্তর না থাকলে বেশিরভাগ খুঁজে পেয়েছি, যেহেতু অন্য কেউ উত্তর দেয় না। আমি কিছু মিস করেছি কিনা দয়া করে আমাকে জানান।

চতুর্থাংশ 1। হ্যাঁ, সংযুক্তি স্ট্রিংয়ে "এনলিস্ট = মিথ্যা" নির্দিষ্ট না করা থাকলে। সংযোগ পুলটি একটি ব্যবহারযোগ্য সংযোগ খুঁজে পেয়েছে। ব্যবহারযোগ্য সংযোগটি হ'ল লেনদেনে তালিকাভুক্ত নয় বা একই লেনদেনে তালিকাভুক্ত এমন একটি।

Q2 এর। দ্বিতীয় সংযোগটি একটি স্বতন্ত্র সংযোগ, যা একই লেনদেনে অংশ নেয়। আমি এই দুটি সংযোগে কমান্ডের মিথস্ক্রিয়া সম্পর্কে নিশ্চিত নই, যেহেতু তারা একই ডাটাবেসের বিরুদ্ধে চলছে, তবে আমি মনে করি একই সময়ে উভয় পক্ষেই কমান্ড জারি করা হলে ত্রুটিগুলি ঘটতে পারে: "ব্যবহারের মাধ্যমে লেনদেন প্রসঙ্গে" ত্রুটিগুলি অন্য অধিবেশন "

চতুর্থাংশ 3। হ্যাঁ, এটি একটি বিতরণ লেনদেনের দিকে প্রসারিত হয়, সুতরাং একই সংযোগের স্ট্রিং সহ একাধিক সংযোগ তালিকাভুক্তকরণ এটি বিতরণ লেনদেনে পরিণত হয়, যা ট্রানজেকশন.কন্ট্রন. ট্রান্সঅ্যাকশন-ইনফরমেশন-এ নন-নাল জিআইডি পরীক্ষা করে নিশ্চিত হওয়া যায় .DistributedIdentifier। * আপডেট: আমি কোথাও পড়েছি যে এটি এসকিউএল সার্ভার ২০০৮-এ স্থির করা হয়েছে, যাতে উভয় সংযোগের জন্য একই সংযোগ স্ট্রিংটি ব্যবহার করা হয় (যতক্ষণ না উভয় সংযোগ একই সময়ে খোলা না থাকে) D এটি আপনাকে কোনও সংযোগ খুলতে এবং লেনদেনের মধ্যে একাধিকবার এটি বন্ধ করার অনুমতি দেয়, যা যত তাড়াতাড়ি সংযোগগুলি খোলার মাধ্যমে এবং যত তাড়াতাড়ি সম্ভব সেগুলি বন্ধ করে সংযোগ পুলের আরও ভাল ব্যবহার করতে পারে।

Q4 ই। নং লেনদেনের সুযোগ সক্রিয় ছিল না এমন সময় কোনও সংযোগ খোলা হয়েছিল, নতুনভাবে তৈরি হওয়া লেনদেনের সুযোগে স্বয়ংক্রিয়ভাবে তালিকাভুক্ত হবে না।

Q5। না আপনি যদি লেনদেনের সুযোগে কোনও সংযোগ না খোলেন বা সুযোগের মধ্যে একটি বিদ্যমান সংযোগ তালিকাভুক্ত না করেন তবে মূলত কোনও ট্রান্সএশন নেই। আপনার আদেশগুলি লেনদেনে অংশ নিতে আপনার সংযোগটি অবশ্যই লেনদেনের সুযোগে স্বয়ংক্রিয়ভাবে বা ম্যানুয়ালি তালিকাভুক্ত হতে হবে।

Q6। হ্যাঁ, কোনও লেনদেনে অংশ নিচ্ছে না এমন সংযোগের আদেশগুলি ইস্যু করা হিসাবে প্রতিশ্রুতিবদ্ধ হয়, যদিও কোডটি কোনও লেনদেনের স্কোপ ব্লকে কার্যকর হয়ে গেছে যা ফিরে গেছে। যদি বর্তমান লেনদেনের সুযোগে সংযোগটি তালিকাভুক্ত না করা হয়, তবে এটি লেনদেনে অংশ নিচ্ছে না, সুতরাং লেনদেনের অঙ্গীকারে তালিকাভুক্ত না হওয়া সংযোগের উপর জারি করা আদেশগুলিতে লেনদেনের প্রতিশ্রুতিবদ্ধ বা প্রতিস্থাপনের কোনও প্রভাব পড়বে না ... কারণ এই লোকটি জানতে পেরেছে । এটা একটা খুব কঠিন এক স্পট, যদি না আপনি স্বয়ংক্রিয় তালিকাভুক্তি প্রক্রিয়া বুঝতে আছে: এটি ঘটে যখন একটি সংযোগ খোলা হয় ভিতরে একটি সক্রিয় লেনদেনের সুযোগ।

Q7। হ্যাঁ. একটি বিদ্যমান সংযোগটি এনলিস্টট্রান্সজেকশন (লেনদেন.কন্টেনাল) কল করে সুস্পষ্টভাবে বর্তমান লেনদেনের সুযোগে তালিকাভুক্ত করা যেতে পারে। আপনি ডিপেন্ডেন্ট ট্রান্সজেকশন ব্যবহার করে লেনদেনে পৃথক থ্রেডে সংযোগ তালিকাভুক্তও করতে পারেন, তবে আগের মতো, আমি নিশ্চিত না যে একই ডাটাবেসের সাথে একই লেনদেনের সাথে জড়িত দুটি সংযোগ কীভাবে ইন্টারঅ্যাক্ট করতে পারে ... এবং ত্রুটিও ঘটতে পারে, এবং অবশ্যই দ্বিতীয় তালিকাভুক্ত সংযোগটি লেনদেনকে বিতরণ লেনদেনের দিকে বাড়িয়ে তোলে।

Q8। একটি ত্রুটি নিক্ষিপ্ত হতে পারে। যদি ট্রানজেকশনস্কোপ অপশন eআমার প্রয়োজন হয় এবং সংযোগটি ইতিমধ্যে একটি লেনদেনের স্কোপ লেনদেনে তালিকাভুক্ত হয়, তবে কোনও ত্রুটি নেই; প্রকৃতপক্ষে, সুযোগের জন্য কোনও নতুন লেনদেন তৈরি হয়নি, এবং লেনদেনের গণনা (@@ ট্রান্সকাউন্ট) বৃদ্ধি পায় না। তবে, আপনি যদি ট্রানজেকশনস্কোপ অপশনটি ব্যবহার করেন R প্রয়োজনীয় তথ্য নতুন, তবে নতুন লেনদেনের স্কোপ লেনদেনে সংযোগটি তালিকাভুক্ত করার চেষ্টা করার পরে আপনি একটি সহায়ক ত্রুটি বার্তাটি পান: "সংযোগটিতে বর্তমানে লেনদেনের তালিকাভুক্ত রয়েছে en বর্তমান লেনদেন শেষ করুন এবং আবার চেষ্টা করুন ry" এবং হ্যাঁ, আপনি যদি লেনদেনটি সম্পূর্ণ করেন তবে সংযোগটি তালিকাভুক্ত করা হয়েছে, আপনি নিরাপদে নতুন লেনদেনে সংযোগটি তালিকাভুক্ত করতে পারেন। আপডেট: আপনি যদি আগে সংযোগে বিগ্রেট ট্রান্সজেকশন বলেছিলেন, আপনি যখন নতুন লেনদেনের সুযোগের লেনদেনের তালিকাভুক্ত করার চেষ্টা করবেন তখন কিছুটা ভিন্ন ত্রুটি নিক্ষেপ করা হবে: "লেনদেনে তালিকাভুক্তি করা যায় না কারণ সংযোগে স্থানীয় লেনদেন চলছে local স্থানীয় লেনদেন শেষ করুন এবং পুনরায় চেষ্টা করা." অন্যদিকে, আপনি সিক্লকনেকশনকে নিরাপদে বিজনেস কল করতে পারবেন যখন এটি কোনও লেনদেনের সুযোগের লেনদেনে অন্তর্ভুক্ত ছিল এবং এটি আসলে একের মধ্যে @@ ট্রান্সকাউন্ট বাড়িয়ে তুলবে, নেস্টেড লেনদেনের সুযোগের প্রয়োজনীয় বিকল্পটি ব্যবহার না করে, যার ফলে এটি ঘটায় না বৃদ্ধি. মজার বিষয় হল, আপনি যদি তারপর প্রয়োজনীয় বিকল্পের সাথে অন্য নেস্টেড লেনদেনের সুযোগ তৈরি করতে যান তবে আপনি কোনও ত্রুটি পাবেন না,

Q9। হ্যাঁ. সক্রিয় লেনদেনের সুযোগটি সি # কোডে কী তা বিবেচনা না করেই সংযোগ তালিকাভুক্ত হওয়া যে কোনও লেনদেনে কমান্ড অংশ নেয়।


11
কিউ 8-এর উত্তর লেখার পরে, আমি বুঝতে পারি যে এই জিনিস ম্যাজিকের জন্য নিয়মের মতো জটিল দেখতে শুরু করেছে: জড়ো হওয়া! এটির চেয়েও খারাপ কারণ, লেনদেনস্কোপ ডকুমেন্টেশন এর কোনও ব্যাখ্যা দেয় না।
ট্রায়ঙ্কো

Q3- এর জন্য, আপনি একই সংযোগের স্ট্রিং ব্যবহার করে একই সাথে দুটি সংযোগ খুলছেন? যদি তা হয় তবে তা হবে একটি বিতরণ লেনদেন (এমনকি এসকিউএল সার্ভার ২০০৮ সহ)
রেন্ডি মনিকা

2
আমি স্পষ্ট করতে পোস্ট সম্পাদনা করছি। আমার বোধগম্যতা হ'ল এসকিউএল সার্ভার সংস্করণ নির্বিশেষে একই সাথে দুটি সংযোগ খোলা থাকার কারণে সর্বদা বিতরণ লেনদেনের কারণ ঘটবে। এসকিউএল ২০০ Before এর আগে একই সংযোগের স্ট্রিং সহ একবারে কেবল একটি সংযোগ খোলার ফলে এখনও ডিটি হয়ে যায়, তবে এসকিউএল ২০০৮ এর সাথে একই সংযোগ স্ট্রিংয়ের সাথে একই সাথে একটি সংযোগ (একবারে দু'বার খোলা না) খোলার কারণ হবে না ডিটি
ত্রিঞ্চো

1
আপনার উত্তরটি কিউ 2 এর জন্য স্পষ্ট করতে, একই থ্রেডে ক্রমানুসারে করা হলে দুটি কমান্ড ঠিকঠাক চলবে।
জ্যারেড মুর

2
এসকিউএল ২০০৮-তে অভিন্ন সংযোগের স্ট্রিংয়ের জন্য কিউ 3 প্রচারের ইস্যুতে, এখানে এমএসডিএন উদ্ধৃতি দেওয়া হয়েছে: এমএসডিএন.মাইক্রোসফটকম /en-us/library/ms172070(v=vs.90).aspx
সিউডোকোডার

19

দুর্দান্ত কাজ ট্রায়ঙ্কো, আপনার উত্তরগুলি আমার কাছে বেশ নির্ভুল এবং সম্পূর্ণ দেখাচ্ছে। আমি অন্য কয়েকটি বিষয় উল্লেখ করতে চাই:

(1) ম্যানুয়াল তালিকাভুক্তি

উপরের আপনার কোডে, আপনি (সঠিকভাবে) ম্যানুয়াল তালিকাভুক্তি এর মতো দেখান:

using (SqlConnection conn = new SqlConnection(connStr))
{
    conn.Open();
    using (TransactionScope ts = new TransactionScope())
    {
        conn.EnlistTransaction(Transaction.Current);
    }
}

তবে সংযোগের স্ট্রিং এ এনলিস্ট = মিথ্যা ব্যবহার করে এটি এটি করা সম্ভব।

string connStr = "...; Enlist = false";
using (TransactionScope ts = new TransactionScope())
{
    using (SqlConnection conn1 = new SqlConnection(connStr))
    {
        conn1.Open();
        conn1.EnlistTransaction(Transaction.Current);
    }

    using (SqlConnection conn2 = new SqlConnection(connStr))
    {
        conn2.Open();
        conn2.EnlistTransaction(Transaction.Current);
    }
}

এখানে আরও একটি বিষয় লক্ষণীয়। যখন কান 2 খোলা হয়, সংযোগ পুল কোডটি জানে না যে আপনি পরে এটি সংযোগ 1 হিসাবে একই লেনদেনে তালিকাভুক্ত করতে চান, যার অর্থ যে সংযোগ 2 কে কান 1 এর চেয়ে আলাদা অভ্যন্তরীণ সংযোগ দেওয়া হয়েছে। তারপরে যখন কান 2 তালিকাভুক্ত করা হয়েছে, এখন 2 টি সংযোগ তালিকাভুক্ত হয়েছে তাই লেনদেনটি এমএসডিটিসিতে প্রচার করতে হবে। এই প্রচারটি কেবলমাত্র স্বয়ংক্রিয় তালিকাভুক্তি ব্যবহার করে এড়ানো যায়।

(2) নেট 4.0 আগে, আমি অত্যন্ত সেটিং সুপারিশ "লেনদেন বাঁধাই = স্পষ্ট আবদ্ধমুক্ত" কানেকশন স্ট্রিং । সুস্পষ্ট আনবাইন্ড সম্পূর্ণ অপ্রয়োজনীয় করে এই সমস্যাটি নেট নেট 4.0.০ এ স্থির করা হয়েছে।

(3) আপনার নিজের ঘূর্ণায়মান CommittableTransactionএবং এটিতে সেট Transaction.Currentকরা মূলত যা TransactionScopeঘটে তা একই জিনিস । এটি খুব কমই আসলে কার্যকর, কেবলমাত্র এফওয়াইআই।

(4) Transaction.Current থ্রেড-স্ট্যাটিক। এর অর্থ এটি Transaction.Currentতৈরি করা থ্রেডে কেবল সেট করা আছে TransactionScope। সুতরাং একাধিক থ্রেড একই কার্যকরকরণ TransactionScope(সম্ভবত ব্যবহার করা Task) সম্ভব নয়।


আমি কেবল এই দৃশ্যের পরীক্ষা করেছি এবং আপনার বর্ণনা অনুসারে এটি কাজ করবে বলে মনে হচ্ছে। অতিরিক্ত হিসাবে, আপনি যদি স্বয়ংক্রিয় তালিকাভুক্তি ব্যবহার করেন, এমনকি যদি আপনি দ্বিতীয় সংযোগটি খোলার আগে "SqlConnication.C ClearAllPools ()" কল করেন, তবে এটি বিতরণ লেনদেনে আরও বাড়বে।
ট্রায়ঙ্কো

যদি এটি সত্য হয়, তবে কোনও লেনদেনে জড়িত কেবলমাত্র একটিমাত্র "আসল" সংযোগ থাকতে পারে। কোনও বিতরণকৃত লেনদেন না বাড়িয়েই কোনও লেনদেন স্কোপ লেনদেনে তালিকাভুক্ত সংযোগটি খোলার, বন্ধ এবং পুনরায় খোলার ক্ষমতা তখন সংযোগ পুল দ্বারা তৈরি একটি বিভ্রম , যা সাধারণত নিষ্পত্তি হওয়া সংযোগটি উন্মুক্ত রেখে দেয় এবং যদি আবার একই সংযোগটি ফিরে আসে তবে - স্বয়ংক্রিয় তালিকাভুক্তির জন্য খোলা।
ট্রায়ঙ্কো

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

যাইহোক, আমি Q1 এর আমার জবাবে ঠিক এটাই ইঙ্গিত দিচ্ছিলাম যখন আমি উল্লেখ করেছি যে সংযুক্তি স্ট্রিংয়ে "এনালিস্ট = মিথ্যা" নির্দিষ্ট না করা থাকলে এটি তালিকাভুক্ত করা হয়েছে, তারপরে পুল কীভাবে একটি উপযুক্ত সংযোগ খুঁজে পাবে সে সম্পর্কে কথা বললাম।
ট্রায়ঙ্কো

মাল্টি-থ্রেডিং যতদূর যায়, যদি আপনি Q2- এর উত্তরটিতে লিঙ্কটি দেখতে যান, আপনি দেখতে পাবেন যে ট্রানজেকশন.কন্টেনার প্রতিটি থ্রেডের অনন্য, আপনি সহজেই একটি থ্রেডে রেফারেন্স অর্জন করতে এবং এটি অন্য থ্রেডে পাস করতে পারেন; তবে দুটি ভিন্ন থ্রেড থেকে টিএসটি অ্যাক্সেস করা খুব সুনির্দিষ্ট ত্রুটির "অন্য সেশনের ব্যবহারে লেনদেন প্রসঙ্গে" ফলাফল দেয়। একটি টিএসটি মাল্টি-থ্রেড করার জন্য আপনাকে অবশ্যই একটি ডিপেন্ডেন্ট ট্রান্সজেকশন তৈরি করতে হবে, তবে সেই মুহূর্তে এটি অবশ্যই একটি বিতরণ লেনদেন হতে হবে, কারণ দুটিকে সমন্বয় করার জন্য আপনাকে একই সাথে কমান্ড এবং এমএসডিটিসি চালানোর জন্য দ্বিতীয় স্বাধীন সংযোগের প্রয়োজন।
ট্রায়ঙ্কো

1

অন্য একটি উদ্ভট পরিস্থিতি আমরা দেখেছি হ'ল আপনি যদি EntityConnectionStringBuilderএটি নির্মাণ করেন তবে তা ব্যর্থ হবে TransactionScope.Currentএবং (আমরা মনে করি) লেনদেনের তালিকাভুক্ত হবে। আমরা ডিবাগার, যেখানে এই পালন করেছি TransactionScope.Current's current.TransactionInformation.internalTransactionশো enlistmentCount == 1নির্মাণের, এবং পূর্বে enlistmentCount == 2পরে।

এটি এড়াতে এটি ভিতরে তৈরি করুন

using (new TransactionScope(TransactionScopeOption.Suppress))

এবং সম্ভবত আপনার অপারেশনের ক্ষেত্রের বাইরে (যখনই আমাদের সংযোগের প্রয়োজন হয় আমরা এটি নির্মাণ করছিলাম)।

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