আমার ফাংশনটি new_customerওয়েব অ্যাপ্লিকেশন দ্বারা প্রতি সেকেন্ডে কয়েকবার (তবে প্রতি সেশনে কেবল একবার) ডেকে আনা হয়। এটি প্রথমে যা করে তা হ'ল customerটেবিলটি লক করা ('উপস্থিত না থাকলে একটি সন্নিবেশ করানো' - এটির একটি সহজ রূপ upsert)।
দস্তাবেজ সম্পর্কে আমার উপলব্ধি হ'ল new_customerপূর্ববর্তী সমস্ত কল শেষ না হওয়া পর্যন্ত অন্যান্য কলগুলিতে কেবল সারি করা উচিত:
লক টেবিলটি কোনও বিবাদমান লকগুলি প্রকাশের প্রয়োজন হলে অপেক্ষা করে একটি টেবিল-স্তরের লক গ্রহণ করে।
এর পরিবর্তে এটি কেন কখনও কখনও অচল হয়ে পড়ে?
সংজ্ঞা:
create function new_customer(secret bytea) returns integer language sql
security definer set search_path = postgres,pg_temp as $$
lock customer in exclusive mode;
--
with w as ( insert into customer(customer_secret,customer_read_secret)
select secret,decode(md5(encode(secret, 'hex')),'hex')
where not exists(select * from customer where customer_secret=secret)
returning customer_id )
insert into collection(customer_id) select customer_id from w;
--
select customer_id from customer where customer_secret=secret;
$$;
লগ থেকে ত্রুটি:
2015-07-28 08:02:58 বিএসটি বিবরণ: প্রক্রিয়া 12380 ডাটাবেস 12141 এর 16438 সম্পর্কের উপর এক্সক্লুসিভ লকের জন্য অপেক্ষা করছে; প্রক্রিয়া দ্বারা ব্লক করা হয়েছে 12379।
প্রক্রিয়া 12379 ডাটাবেস 12141 এর 16438 সম্পর্কিত এক্সক্লুসিভ লকের জন্য অপেক্ষা করে; প্রক্রিয়া দ্বারা ব্লক করা 12380।
প্রক্রিয়া 12380: নতুন_কাস্টমারের নির্বাচন করুন (ডিকোড ($ 1 :: পাঠ্য, 'হেক্স'))
প্রক্রিয়া 12379: নতুন_কাস্টমারের নির্বাচন করুন (ডিকোড ($ 1 :: পাঠ্য, 'হেক্স'))
2015-07-28 08:02:58 বিএসটি ইঙ্গিত: ক্যোয়ারী বিশদের জন্য সার্ভার লগ দেখুন।
2015-07-28 08:02:58 বিএসটি চুক্তি: এসকিউএল ফাংশন "new_customer" বিবৃতি 1
2015-07-28 08:02:58 বিএসটি বিবৃতি: নতুন_কাস্টমারের নির্বাচন করুন (ডিকোড ($ 1: পাঠ্য, 'হেক্স'))
সম্পর্ক:
postgres=# select relname from pg_class where oid=16438;
┌──────────┐
│ relname │
├──────────┤
│ customer │
└──────────┘
সম্পাদনা:
আমি একটি সহজ-ইশ প্রজননযোগ্য পরীক্ষার কেস পেতে সক্ষম হয়েছি। আমার কাছে এটি এক ধরণের রেসের শর্তের কারণে বাগের মতো দেখাচ্ছে।
স্কিমা:
create table test( id serial primary key, val text );
create function f_test(v text) returns integer language sql security definer set search_path = postgres,pg_temp as $$
lock test in exclusive mode;
insert into test(val) select v where not exists(select * from test where val=v);
select id from test where val=v;
$$;
বাশ স্ক্রিপ্ট দুটি ব্যাশ সেশনে একই সাথে চলবে:
for i in {1..1000}; do psql postgres postgres -c "select f_test('blah')"; done
ত্রুটি লগ (সাধারণত 1000 কলের উপরে কয়েক মুখ্য অচলতা):
2015-07-28 16:46:19 BST ERROR: deadlock detected
2015-07-28 16:46:19 BST DETAIL: Process 9394 waits for ExclusiveLock on relation 65605 of database 12141; blocked by process 9393.
Process 9393 waits for ExclusiveLock on relation 65605 of database 12141; blocked by process 9394.
Process 9394: select f_test('blah')
Process 9393: select f_test('blah')
2015-07-28 16:46:19 BST HINT: See server log for query details.
2015-07-28 16:46:19 BST CONTEXT: SQL function "f_test" statement 1
2015-07-28 16:46:19 BST STATEMENT: select f_test('blah')
সম্পাদনা 2:
@ টাইপারউবটি ফাংশনের বাইরের সাথে একটি বৈকল্পিকের পরামর্শlock table দিয়েছে:
for i in {1..1000}; do psql postgres postgres -c "begin; lock test in exclusive mode; select f_test('blah'); end"; done
আকর্ষণীয়ভাবে এটি অচলাবস্থাগুলি দূর করে।
customerব্যবহার করা হয় যা কোনও দুর্বল লক ধরে ফেলবে? তাহলে এটি লক আপগ্রেড সমস্যা হতে পারে।