PDA

View Full Version : PHP و MySQL ، آیدی های هدر رفته!



arenaw
دوشنبه 28 اسفند 1391, 18:38 عصر
سلام
من یه فیلد اصلی به اسم آیدی توی تیبلم دارم. مثلا 36 تا هم رکورد دارم (آیدی ها از 1 تا 36)
اگه من اومدم مثلا رکورد با آیدی 18 رو پاک کردم، بعدش وقتی خواستم یه رکورد دیگه اضافه کنم به جای اینکه شماره 37 رو به آیدی رکورد جدید اختصاص بده، شماره 18 رو بذاره.
البته میشه با پی اچ پی بیام دونه دونه بشمرم از اول اگه عددی جا مونده بود، به صورت دستی آیدی رکورد جدیدو وارد کنم، ولی به نظرم استاندارد نمیاد!
(علت این کارم : چون نمیدونم آیا وقتی آخرین رکورد با آیدی بزرگترین عدد اینتیجر، گذاشته شد، واسه بعدیا ازون عددهای حذف شده استفاده میشه یا ظرفیت تیبل به حداکثر میرسه!)

eshpilen
دوشنبه 28 اسفند 1391, 18:50 عصر
در فیلدهای auto-increment از یک آیدی دوباره استفاده نمیشه. آیدی همواره درحال افزایش است.
و البته این مزایای خودش رو هم داره.
نگران پر شدن بازهء اعداد هم نباشید. میتونید نوع فیلد رو از نوع عددی دارای بازهء بقدر کافی بزرگ تعییین کنید.

eshpilen
دوشنبه 28 اسفند 1391, 19:03 عصر
در اینجاها درمورد به حداکثر مقدار رسیدن فیلدهای auto-increment سوال شده:
http://stackoverflow.com/questions/2615417/what-happens-when-auto-increment-on-integer-column-reaches-the-max-value-in-data
http://stackoverflow.com/questions/261815/upper-limit-for-autoincrement-primary-key-in-sql-server
نوشته زمانیکه مقدار فیلد auto-increment به حداکثر میرسه، کوئری های Insert با خطا مواجه میشن و امکان درج رکورد جدید در جدول وجود نداره. و برای بعضی افراد این مسئله پیش آمده!

ولی اولا که در کاربردهای عادی چنین چیزی نباید براتون پیش بیاد. منظورم سایتهای با ترافیک معمولی و دیتابیسهایی که خیلی بزرگ نیستن است.
مثلا نوع Int که 32 بیتی است تا بیش از 4 میلیارد رکورد/Insert جا داره. البته من فرض کردن که اون رو Unsigned گرفته باشید.
نوع BIGINT (بازهء 64 بیتی) بذارید که دیگه بنظرم توی دنیا هیچکس نمیتونه پرش کنه!!

MMSHFE
سه شنبه 29 اسفند 1391, 06:47 صبح
در تکمیل توضیحات دوست خوبم eshpilen این نکته رو هم اضافه کنم که اگه میخواین همیشه Auto Increment در حداقل خودش باقی بمونه، بعد از DELETE این کوئری رو اجرا کنید:
ALTER TABLE `table_name` AUTO_INCREMENT=1
اینطوری فیلد Auto Increment شما برابر با یک واحد بیشتر از آخرین رکورد موجود خواهد شد. البته در اصل این کوئری باید اون فیلد رو 1 بگذاره ولی چون عدد بزرگتر از 1 توی دیتابیستون دارین، میاد تمام رکوردها رو چک میکنه و یکی بیشتر از آخرین عدد رو درنظر میگیره.
موفق باشید.

eshpilen
سه شنبه 29 اسفند 1391, 09:43 صبح
ولی سعی کنید به Auto Increment کاری نداشته باشید؛ در کارش دخالت نکنید!
اینکه در Auto Increment از یک آیدی دوباره استفاده نمیشه مزایای مهمی داره و از ایجاد باگهای پنهان در برنامه ها در شرایط مختلف جلوگیری میکنه.
یک مثال خیالی و ساده میزنم با اغماض:
فرض کنید مثلا مدیر/ادمین، یک صفحه که رکوردهای دیتابیس رو لیست کرده باز کرد، کنار هر رکورد هم دکمه ای جهت حذف اون هست، طبیعتا حذف هر رکورد با پاس دادن Auto Increment id اون رکورد از اون صفحه به سرور انجام میشه، حالا فرضا در همون بازهء زمانی که صفحهء مدیریت مدیر بازه در سمت سرور به علت انجام هر عملیات یا پردازشی یک یا چند رکورد حذف میشه، و بعدهم مجددا یک یا چند رکورد درج میشه، در این حالت اگر آیدی رکوردهای جدید از آیدی رکوردهای حذف شدهء قبلی استفاده کنن اونوقت یک باگ ظریف در برنامه بوجود میاد، به این شکل که ممکنه مدیر دستور حذف رکوردهایی رو بده که الان وجود ندارن اما آیدی اونا به رکوردهای جدیدی اختصاص داده شده، در نتیجه رکوردهای جدید اشتباها حذف میشن.
حتی ممکنه اون صفحهء مدیریت رو که قبل از حذف رکوردها و درج رکوردهای جدید واکشی شده بود، مدیر از کش مرورگر باز کنه.

حالا این مثالی که من زدم مثال ساده شده و شاید تاحدی غیرواقعگرایانه بود، ولی خواستم مثال ساده و کوتاه و قابل فهم باشه. وگرنه حالتهای پیچیده تری هم میتونن پیش بیان که فقط در جریان برنامه نویسی و تست و توسعه یا موقعی که باگها عملا بروز کنن و موجب مشکل و خسارت بشن میشه با تحقیق و تحلیل اونا رو کشف کرد و فهمید.

بعنوان مثال دیگه، شاید شما مثلا جهت عملیات خاصی، یک لینک با آیدی مشخصی رو به ایمیل کاربر ارسال کرده باشید. شاید این لینک کلیدی هم داشته باشه یا نداشته باشه، ولی بهرحال اصل قضیه رو تغییر نمیده (چون مثلا جدول کلیدها میتونه جدا باشه و آیدی مربوطه همراه با کلید مربوطه هنوز در اون جدول موجود باشه.) طبیعتا هروقت کاربر ایمیل خودش رو باز کنه (حتی مدتها بعد) و روی اون لینک عمدا یا غیرعمدا کلیک کنه، احتمال بروز باگ وجود خواهد داشت.

بذارید دوتا عدد خالی بمونه و هدر بره. هیچ مشکلی نیست.
اینم مثل وسواس در بهینه سازی هست که همینطور بخواید عددها مرتب باشن و جای خالی نداشته باشید.
البته مرتب بودن و جای خالی نداشتن در بعضی عملیات کار رو خیلی ساده تر میکنه و برای برنامه نویس کار کردن با این فرض خیلی راحتتر میشه؛ ولی خب چاره ای نیست دیگه! از اونور مشکلات دیگری ایجاد میکنه و هیچ استاندارد هم نیست بنظرم.

اگر از آیدی تکراری استفاده کنید، همیشه در کوچکترین عملیات باید به این فکر کنید که آیا ممکنه آیدی مربوط به رکورد قدیمی با آیدی رکورد جدید تداخل کنه یا نه. تازه اینم لزوما 100% نمیشه به همهء حالات و احتمالات ممکن پی برد و اونا رو پیشبینی کرد.

آیدی Auto Increment باید یکتا باشه. برای هر رکورد در تاریخ اجرای برنامه! حتی اگر اون رکورد فقط یک لحظه وجود داشته.
اینطوری احتمال تداخل و بعضی باگهای پیچیده و پنهان به صفر میرسه.
من بخاطر همین در پروژم دست آخر تقریبا برای تمام جدول ها فیلد Auto Increment گذاشتم (اولش استفاده نمیکردم و فکر میکردم لزومی نداره، ولی بعد دیدم بهترین چیزه و حتی جاهایی که فکر نمیکنی باید جدول Auto Increment داشته باشه).