How PostgreSQL Handles Constraints in Read Committed Isolation Level [Arabic]
في ال read committed isolation level معروف ان كل transaction بتاخد snapshot من الداتا وتتعامل معاها وبالتالي اللي كل transaction بتعمله مفيش اي transaction تانية بتشوفه الا لما يحصل commit الطريقة دي اسمها MVCC (Multi version concurrency control). بس السؤال بقا في حالة لو عندي constraint من التلاتة دول :Primary key, Unique, EXCLUDE USING. في الحالة دي مش هينفع يبقى في نفس الvalue في نفس ال column بس بما ان كل transaction بتاخد snapshot تشتغل فيها ففي حالة لو في 2 concurrent transactions الكلام دا معناه ان وارد كل واحده فيهم تحط نفس ال value في column عليه constraint وكدا لازم واحدة منهم تترفض والا ال constraints دي ملهاش لازمة كدا. طيب ايه اللي بيحصل بقا من postgres عشان نتفادى الموضوع دا؟ خلينا نشوف ايه اللي بيحصل عملياً وبعدها نرجع نشرح ايه اللي بيتم
كدا احنا شوفنا ال transaction بتـstuck ومبترجعش اي feedback سواء بإنها تقولك ان حصل insertion فعلا او ترجع error عادي و دا لأنها مستنية ال transaction التانية تحدد موقفها اذا كانت هتعمل commit وبالتالي ال value دي بقت موجودة بالفعل وانت بتحاول تدخل duplicated value فبترجعلك ERROR او ان ال transaction عملت rollback وبالتالي ال value اللي انت عايز تدخلها دي مش موجودة وتقدر تضيفها عادي و ال insertion هيتم. السؤال بقا الكلام دا بيحصل ازاي و ليه في حين ان المفروض transaction A مش شايفة ولا تعرف ايه اللي transaction B بتعمله؟ قالك بقا postgres بتاخد بالها من الموضوع دا بطريقة non-MVCC وهي انها بتبص على ال data structure بتاع ال index اللي موجود. انت لما بتضيف داتا في column عليه index الداتا دي بتروح في ال index data structure وبالتالي postgres شايفة اللي كل transaction بتعمله حتى لو هي لسه مش committed. بس لحظة! مين جاب سيرة ال index? مين قال ان في index على ال column دا؟ قالك بقا postgres بتعمل index على اي column عليه ال constraints دي من غير ماحضرتك تطلب منها انها تعمله وهي فعلا بتعمله عشان تستفيد منه في حل ال case اللي احنا بنناقشها دي. تقدر تشوف ال indexes الموجودة عندك من خلال الأمر دا
SELECT indexname FROM pg_indexes WHERE tablename = your_table_name ;
زي ما واضح في الصورة دي انا عملت table وعملت id PK, username UNIQUE وبعدها جبت ال index اللي موجوده ولقيته عمل على ال username زي ما واضح
طيب ممكن يتبادر الى ذهنك سؤال مهم ماذا لو كل transaction منهم عملت insert ب value التانية بتحاول تعمل insert بنفس ال value يعني حسب الكلام اللي قولناه فوق ان كل واحدة كدا هتـstuck وتستنى التانية اللي هي برضو هتبقى stucked وبكدا كل واحدة مستنية التانية تحدد موقفها؟ ايوا بالضبط هو دا ال deadlock بعينه. postgres هتقولك deadlock detected
وهتنجح واحدة منهم وهترجع error للتانية، اللي هتنجح هي اللي دخلت ال deadlock الأول زي ما واضح في الصورتين دول.
لو في اي feedback تقدر توصلي على twitter @AhmedMonm1
المصادر:
1- كورس حسين ناصر على يوديميconcurrency control chapter link: https://www.udemy.com/course/database-engines-crash-course/
2- The Art of PostgreSQL, Chapter 8 Indexing Strategy, Indexing for Constraints
Subscribe to my newsletter
Read articles from Ahmed Mone'm directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ahmed Mone'm
Ahmed Mone'm
Software Engineer, mainly I'm backend developer but I can do some more cool stuff. We can discuss some topics in Node.js, AWS, Scalability, Databases and System design.