পিএইচপি ফাইল_পুট_কন্টেন্টস ফাইল লকিং


9

দ্য সেনারিও:

আপনার প্রতিটি লাইনে একটি স্ট্রিং (গড় বাক্য মূল্য মূল্য) সহ একটি ফাইল রয়েছে। যুক্তি দেখানোর জন্য এই ফাইলটি 1Mb আকারের (হাজার হাজার লাইন) বলে দিন।

আপনার কাছে একটি স্ক্রিপ্ট রয়েছে যা ফাইলটি পড়ে, নথির মধ্যে কিছু স্ট্রিং পরিবর্তন করে (কেবল সংযোজন নয় কিছু লাইন মুছে ফেলা ও সংশোধন করে) এবং তারপরে নতুন ডেটা দিয়ে সমস্ত ডেটা ওভাররাইট করে।

প্রশ্নসমুহ:

  1. 'সার্ভার' পিএইচপি, ওএস বা httpd ইত্যাদি এর মতো সমস্যাগুলি থামানোর জন্য ইতিমধ্যে ব্যবস্থা আছে (কোনও লেখার মধ্য দিয়ে অর্ধেক পাঠ / পড়া)?

  2. যদি এটি হয় তবে দয়া করে এটি কীভাবে কাজ করে তা ব্যাখ্যা করুন এবং প্রাসঙ্গিক ডকুমেন্টেশনের উদাহরণ বা লিঙ্ক দিন।

  3. যদি তা না হয় তবে আমি সক্ষম বা সেট আপ করতে সক্ষম এমন কিছু জিনিস রয়েছে যেমন কোনও লেখা শেষ না হওয়া পর্যন্ত কোনও ফাইলকে লক করা এবং অন্য সমস্ত পাঠক এবং / অথবা লেখাগুলি ব্যর্থ করে পূর্ববর্তী স্ক্রিপ্টটি লেখা শেষ না হওয়া পর্যন্ত?

আমার অনুমান এবং অন্যান্য তথ্য:

  1. প্রশ্নে থাকা সার্ভারটি পিএইচপি এবং অ্যাপাচি বা লাইটটিপিডি চলছে।

  2. যদি স্ক্রিপ্টটি একজন ব্যবহারকারী দ্বারা ডাকা হয় এবং ফাইলটিতে লেখার মধ্য দিয়ে অর্ধেক হয়ে থাকে এবং অন্য ব্যবহারকারী সেই মুহুর্তে ফাইলটি পড়েন। যে ব্যবহারকারী এটি পড়েন তিনি পুরো দস্তাবেজটি পাবেন না, কারণ এটি এখনও লেখা হয়নি। (যদি এই অনুমানটি ভুল হয় তবে দয়া করে আমাকে সংশোধন করুন)

  3. আমি কেবল পিএইচপি রচনা এবং একটি পাঠ্য ফাইল পড়ার সাথে উদ্বিগ্ন এবং বিশেষত ফাংশন "ফোপেন" / "ফাইরাইট" এবং প্রধানত "ফাইল_পুট_কন্টেন্টস"। আমি "ফাইল_পুট_কন্টেন্টস" ডকুমেন্টেশনটি দেখেছি কিন্তু "LOCK_EX" পতাকাটি কী বা কী করছে তার বিশদের স্তর বা একটি ভাল ব্যাখ্যা খুঁজে পাইনি।

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


2
আমি আপনাকে অভিজ্ঞতা থেকে বলতে পারি যে পিএইচপি (1 মেগাবাইট সত্যিই এত বড় নয়, তবে এখনও) বড় ফাইলগুলি থেকে পড়া এবং লেখা জটিল (এবং ধীর) হতে পারে। আপনি সবসময় ফাইলটি লক করতে পারেন তবে কেবল একটি ডাটাবেস ব্যবহার করার জন্য এটি সম্ভবত সহজ এবং নিরাপদ হতে পারে।
নালুউজারএক্সসেপশন

আমি জানি ডিবি ব্যবহার করা ভাল। দয়া করে প্রশ্নটি পড়ুন (সর্বশেষ অনুচ্ছেদ 4)
হোজ্জা

2
আমি প্রশ্নটি পড়েছি; আমি বলছি এটি দুর্দান্ত ধারণা নয় এবং এর চেয়ে আরও ভাল বিকল্প রয়েছে।
নালুউজারএক্সেপশন

2
file_put_contents()শুধু একটি মোড়কের হয় fopen()/fwrite()নাচ, LOCKEXএকই যেন আপনি কল চাই না flock($handle, LOCKEX)
ইয়ানিস

2
@ হোজ্জা এজন্য আমি একটি মন্তব্য পোস্ট করেছি, উত্তর নয়।
নাল ইউজারএক্সেপশন

উত্তর:


4

1) না 3) না

মূল প্রস্তাবিত পদ্ধতির সাথে বেশ কয়েকটি সমস্যা রয়েছে:

প্রথমত, কিছু ইউনিক্স-মতো সিস্টেম যেমন লিনাক্সের লকিং সমর্থন কার্যকর নাও করা যেতে পারে। ওএস ডিফল্টরূপে ফাইলগুলি লক করে না। আমি সিস্কলগুলি এনওপি (নন-অপারেশন) হয়ে দেখেছি, তবে এটি কয়েক বছর আগে, সুতরাং আপনার আবেদনটির উদাহরণ অনুসারে কোনও লক সেট অন্য কোনও উদাহরণের দ্বারা সম্মানিত কিনা তা আপনাকে যাচাই করতে হবে। (অর্থাত্ 2 সমবর্তী দর্শনার্থী)। যদি লকিংটি এখনও কার্যকর না হয় [খুব সম্ভবত এটি হয়], ওএস আপনাকে সেই ফাইলটি ওভাররাইট করতে দেয়।

পারফরম্যান্স কারণে লাইন-লাইন বড় ফাইলগুলি পড়া সম্ভব নয়। আমি পুরো ফাইলটিকে মেমরিতে লোড করতে file_get_contents () ব্যবহার করার পরামর্শ দিচ্ছি এবং তারপরে লাইনগুলি পেতে এটি বিস্ফোরিত হবে ()। বিকল্পভাবে, ব্লকগুলিতে ফাইলটি পড়ার জন্য ফ্রেড () ব্যবহার করুন। লক্ষ্যটি হ'ল পঠিত কলগুলির সংখ্যা হ্রাস করা।

ফাইল লক করার ক্ষেত্রে:

LOCK_EX অর্থ একচেটিয়া লক (সাধারণত লেখার জন্য)। কেবলমাত্র একটি প্রক্রিয়া একটি নির্দিষ্ট সময়ে প্রদত্ত ফাইলের জন্য একচেটিয়া লক ধরে রাখতে পারে। LOCK_SH একটি ভাগ করা লক (সাধারণত পড়ার জন্য), একাধিক প্রক্রিয়া একটি নির্দিষ্ট সময় একটি প্রদত্ত ফাইলের জন্য একটি ভাগ করা লক ধরে রাখতে পারে। LOCK_UN ফাইলটি আনলক করে। আপনি ফাইল_জেট_কন্টেন্টস () http://en.wikedia.org/wiki/File_locking#In_Unix- Like_s সিস্টেমে ব্যবহার করলে আনলকিং স্বয়ংক্রিয়ভাবে সম্পন্ন হয়

মার্জিত সমাধান

পিএইচপি ডেটা স্ট্রিম ফিল্টারগুলিকে সমর্থন করে যা ফাইলগুলিতে বা অন্যান্য ইনপুট থেকে ডেটা প্রক্রিয়াকরণের উদ্দেশ্যে are আপনি স্ট্যান্ডার্ড এপিআই ব্যবহার করে সঠিকভাবে এমন একটি ফিল্টার তৈরি করতে চাইতে পারেন। http://php.net/manual/en/function.stream-filter-register.php http://php.net/manual/en/filters.php

বিকল্প সমাধান (3 ধাপে):

  1. একটি সারি তৈরি করুন। একটি ফাইল নাম প্রক্রিয়াকরণের পরিবর্তে, মুলতুবি / এবং প্রক্রিয়াজাত / প্রক্রিয়াধীন কোথাও অনন্য ফাইলের নাম সংরক্ষণ করতে ডাটাবেস বা অন্যান্য প্রক্রিয়া ব্যবহার করুন। এইভাবে কিছুই ওভাররাইট হয় না। ডেটাবেস অতিরিক্ত তথ্য যেমন মেটাডেটা, নির্ভরযোগ্য টাইমস্ট্যাম্পস, প্রক্রিয়াজাতকরণ ফলাফল এবং অন্যান্য সংরক্ষণের জন্যও কার্যকর হবে।

  2. কয়েক এমবি পর্যন্ত ফাইলগুলির জন্য, পুরো ফাইলটি মেমরিতে পড়ুন এবং তারপরে এটি প্রক্রিয়া করুন (ফাইল_জেট_কন্টেন্টস) (বিস্ফোরিত () + ফোরচ ())

  3. বড় ফাইলগুলির জন্য ব্লকগুলিতে ফাইলটি (যেমন 1024 বাইট) পড়ুন এবং প্রসেস + প্রতিটি ব্লককে রিয়েল-টাইমে পড়ার হিসাবে লিখুন (শেষ লাইনের বিষয়ে সতর্কতা যা শেষ হয় না \ n এটি পরবর্তী ব্যাচে প্রক্রিয়া করা প্রয়োজন)


1
"আমি সিস্কলগুলি এনওপি (অপারেশন) হতে দেখেছি ..." কোন কার্নেল?
ম্যাসিমো

1
"পারফরম্যান্সের কারণে বড় বড় ফাইলগুলি লাইন বাই লাইনে পড়া সম্ভব নয় I পুরো ফাইলটি মেমরিতে লোড করার জন্য আমি ফাইল_গেট_কন্টেন্টস () ব্যবহার করার পরামর্শ দিচ্ছি ..." এটি বোধবুদ্ধি নয়। আমি বলতে পারি: পারফরম্যান্সের কারণে বড় ফাইলগুলি মেমোরিতে পড়েন না ... কী করবেন তা অন্যান্য অনেক কারণের উপর নির্ভর করে।
ম্যাসিমো

4

আমি জানি এটি বয়স্ক, তবে কোনও ক্ষেত্রে যদি এটি চালিত হয়। আইএমএইচও করার উপায়টি এরকম:

1) file_get_contents ('original.txt') ব্যবহার করে মূল ফাইলটি (যেমন original.txt) খুলুন।

2) আপনার পরিবর্তনগুলি / সম্পাদনা করুন।

3) ফাইল_পুট_কন্টেন্টস ('original.txt.tmp') ব্যবহার করুন এবং এটি একটি অস্থায়ী ফাইল original.txt.tmp এ লিখুন।

4) তারপরে tmp ফাইলটি মূল ফাইলটিতে সরিয়ে নিয়ে আসল ফাইলটি প্রতিস্থাপন করুন। এর জন্য আপনি নাম পরিবর্তন করতে পারেন ('original.txt.tmp', 'original.txt')।

সুবিধা: ফাইলটি প্রক্রিয়া করার সময় এবং ফাইলটিতে লিখিত থাকাকালীন লক করা হয়নি এবং অন্যরা এখনও পুরাতন সামগ্রীটি পড়তে পারে। কমপক্ষে লিনাক্স / ইউনিক্স বাক্সগুলির নাম পরিবর্তন একটি পারমাণবিক অপারেশন। ফাইল লেখার সময় যে কোনও বাধা আসল ফাইলটিকে স্পর্শ করে না। কেবল একবার ফাইলটি ডিস্কে পুরোপুরি লেখা হয়ে গেলে এটি সরানো হয়। Http://php.net/manual/en/function.rename.php এই মন্তব্যগুলিতে আরও আকর্ষণীয় পড়ুন

কমেন্টগুলিকে সম্বোধন করতে সম্পাদনা করুন (মন্তব্য করার জন্যও):

/programming/7054844/is-rename-atomic এর আরও রেফারেন্স রয়েছে যা আপনি ফাইল-সিস্টেম জুড়ে অপারেটিং করে চললে আপনার কী করা দরকার।

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

পুনর্নামকরণ ফাইলটির নামকরণের প্রক্রিয়াটির জন্য আদর্শভাবে নামকরণ করা উচিত যাতে নিশ্চিত করা যায় যে 2 টি প্রক্রিয়া একই কাজ না করে। তবে অবশ্যই এটি একই সময়ে একাধিক ব্যক্তির দ্বারা একই ফাইলের সম্পাদনা রোধ করে না। তবে কমপক্ষে ফাইলটি অক্ষত থাকবে (শেষ সম্পাদনা জিতবে)।

পদক্ষেপ 3) এবং 4) এর পরে এটি হয়ে যাবে:

$tempfile = uniqid(microtime(true)); // make sure we have a unique name
file_put_contents($tempFile); // write temp file
rename($tempfile, 'original.txt'); // ideally on the same filesystem

হুবহু আমি পাশাপাশি প্রস্তাব করতে চেয়েছিলেন কি। তবে ডেটা ক্লোবার প্রতিরোধের জন্য পড়ার সময় আমি একটি ভাগ করা লকও অর্জন করব।
মার্কো-এ

নাম পরিবর্তন একই ডিস্কে একটি পারমাণবিক অপারেশন, বিভিন্ন ডিস্কে নয়।
Xnoise

করতে সত্যিই একটি অনন্য tempfile নাম গ্যারান্টি, এছাড়াও আপনি ব্যবহার করতে পারেন ফাংশন, যা atomically একটি ফাইল এবং আয় ফাইলের নাম তৈরি করে। tempnam
ম্যাথিজস কুইজমান

1

ফাইল_পুট_কন্টেন্টস () এর জন্য পিএইচপি ডকুমেন্টেশনে আপনি উদাহরণস্বরূপ LOCK_EX এর জন্য # 2 ব্যবহারের সন্ধান করতে পারেন :

file_put_contents('somefile.txt', 'some text', LOCK_EX);

LOCK_EX একটি সঙ্গে একটি ধ্রুবক পূর্ণসংখ্যা চেয়ে মধ্যে কিছু ফাংশন ব্যবহার করা যেতে পারে মান , bitwise

ফাইলগুলির জন্য লকিং নিয়ন্ত্রণ করার জন্য একটি নির্দিষ্ট ফাংশন রয়েছে: ফ্লক () পদ্ধতিতে।


যদিও এটি আকর্ষণীয় এবং কিছু পরিস্থিতিতে কার্যকর হতে পারে, যখন কোনও ফাইল পড়া, সংশোধন ও পুনরায় লেখার সময় লকটি পড়ার আগে তা অর্জন করা উচিত এবং পুরোপুরি নতুন করে লেখা না হওয়া পর্যন্ত এটি রক্ষণ করা উচিত (অন্যথায় অন্য কোনও প্রক্রিয়া একটি পুরানো অনুলিপি পড়তে পারে এবং এটি পরিবর্তন করতে পারে) আপনার প্রক্রিয়া শেষ হওয়ার পরে ফিরে আসুন)। আমি বিশ্বাস করি না যে এটি দিয়ে অর্জন করা যায় file_get/put_contents
জুলুস

0

আপনি যে বিষয়টির কথা উল্লেখ করেননি তা হ'ল রেস শর্তগুলি যেখানে আপনার স্ক্রিপ্টের দুটি উদাহরণ প্রায় একই সময়ে চলছে, উদাহরণস্বরূপ এই ঘটনাগুলির ক্রম:

  1. স্ক্রিপ্ট উদাহরণ 1: ফাইল পড়ে
  2. স্ক্রিপ্ট উদাহরণ 2: ফাইল পড়ে
  3. স্ক্রিপ্ট উদাহরণ 1: ফাইল পরিবর্তন লিখেছে
  4. স্ক্রিপ্ট উদাহরণ 2: প্রথম স্ক্রিপ্ট ইনস্ট্যান্সের ফাইলগুলিতে তার নিজস্ব পরিবর্তনগুলি পরিবর্তনগুলি ওভাররাইট করে (যেহেতু এই মুহুর্তে এটির পড়াটি বাসি হয়ে গেছে)।

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

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