JavaRush /Kurslar /All lectures for UZ purposes /Ma'lumotlar bazasi bilan ishlashda tranzaksiyalar

Ma'lumotlar bazasi bilan ishlashda tranzaksiyalar

All lectures for UZ purposes
Daraja, Dars
Mavjud

Tranzaksiyalar nima uchun kerak

Ko'pincha ma'lumotlar bazasi bilan ishlaganda har xil ko'p qurilmalarni bajarish kerak bo'lgan vaziyat paydo bo'ladi, lekin ular faqat birga ma'no anglatadi.

Masalan, biz bank dasturini yozmoqdamiz, u uchta narsani bajarishi kerak:

  • Mijozning hisobidan pul olish
  • Oluvchining hisobiga pul qo'shish
  • O'tkazma haqida ma'lumotlarni “o'tkazmalar jurnaliga” yozish

Agar shu harakatlardan biri amalga oshirilganda xato yuz bersa, qolgan ikki harakatni ham bekor qilish kerak. Mijozdan pul olish va oluvchiga qo'shmaslik boʻlishi mumkin emas? Yoki oluvchiga qo'shish, lekin mijozdan olmaslik?

Aynan mana shu turli harakatlarni bir guruh qiladigan mantiqiy ittifoq tranzaksiya deb ataladi. Boshqacha qilib aytganda, tranzaksiya — bu birgalikda bajarilishi kerak bo'lgan harakatlar guruhi. Agar biron-bir harakat bajarilmasa yoki xatolik bilan bajarilsa, qolgan harakatlar bekor qilinishi kerak.

Odatda tranzaksiyaning uchta holati bor:

  • initial state — har tomonlama harakatlar guruhidan oldingi tizim holati
  • success state — har tomonlama harakatlar guruhidan keyingi tizim holati
  • failed state — biror narsa noto'g'ri ketdi

Odatda uchta buyruq mavjud:

  • begin/start — har tomonlama harakatlar guruhi boshlanishidan oldin bajariladi
  • commit — tranzaksiya harakatlar guruhidan keyin bajariladi
  • rollback — tizimni failed holatdan initial holatga qaytarish jarayonini boshlaydi

Bu shunday ishlaydi.

Birinci tranzaksiya ochilishi kerak — begin() yoki start() metodini chaqirish. Ushbu metod chaqirilishi tizim holatini belgilaydi, agar bir narsa noto'g'ri ketgan bo'lsa, shu holatga qaytamiz uchun.

Keyin barcha harakatlar bajariladi, ular mantiqiy guruhda — tranzaksiya.

So'ng commit() metodi chaqiriladi. Uning chaqirilishi har tomonlama harakatlar guruhining oxirini belgilaydi va odatda bu harakatlarni amaliyotda amalga oshirishni boshlaydi.

Eslab qol, qanday qilib FileWriter ga biror narsa yozgan edik: dastlab yozgan hamma narsa xotirada saqlanadi, keyin flush() metodi chaqirilganda, xotira buferidagi barcha ma'lumotlar diskka yoziladi. Bu yerda flush() tranzaksiya kommiti hisoblanadi.

Xo'sh, agar tranzaksiya ishlash davomida xatolik yuz bersa, boshlang'ich holatga qaytarish jarayonini boshlash kerak. Ushbu jarayon rollback() deb ataladi va odatda bir xil nomli metod javobgar bo'ladi.

Qo'pol qilib aytganda, tranzaksiyani tugatishning ikkita usuli mavjud:

  • COMMIT — kiritilgan barcha o'zgartishlarni tasdiqlash
  • ROLLBACK — kiritilgan barcha o'zgartishlarni bekor qilish

JDBC da tranzaksiyalar

Deyarli har bir DBMS tranzaksiyalar bilan ishlay oladi. Shunday qilib, JDBC ham bu ishni qo'llab-quvvatlaydi. Hammasi juda oddiy amalga oshirilgan.

Birinchidan, Statement obyekti execute() metodini har bir chaqiruvi alohida tranzaksiyada bajariladi. Buning uchun Connection da AutoCommit parametri mavjud. Agar u true ga o'rnatilgan bo'lsa, commit() har bir execute() metodi chaqiruvdan keyin chaqiriladi.

Ikkinchidan, agar bir nechta buyruqlarni bir tranzaksiyada bajarishni xohlasangiz, quyidagi tartibda amalga oshiriladi:

  • AutoCommit ni o'chirasiz
  • buyruqlarni chaqirasiz
  • commit() metodini ochiq tarzda chaqirasiz

Bu juda oddiy ko'rinadi:


  connection.setAutoCommit(false);

  Statement statement = connection.createStatement();
  int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  int rowsCount3 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
 
  connection.commit();

Agar commit() metodi serverda ishlayotgan paytda xatolik yuz bersa, SQL-server uchta amalni ham bekor qiladi.

Lekin ba'zi vaziyatlarda xatolik hali mijoz tomonida yuzaga keladi va biz commit() metodini chaqirishga yetib bormaganmiz:


  connection.setAutoCommit(false);

  Statement statement = connection.createStatement();
  int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  int rowsCount3 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
 
  connection.commit();

Agar bir executeUpdate() ishlayotgan paytda xatolik yuz bersa, commit() metodi chaqirilmaydi. Harakatlarni bekor qilish uchun, rollback() metodini chaqirishingiz kerak. Odatda, bu quyidagicha amalga oshiriladi:


  try{
  	connection.setAutoCommit(false);
 
  	Statement statement = connection.createStatement();
  	int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount3 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
 
	connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

Saqlash nuqtalari

JDBC 3.0 bilan tranzaksiya bekor qilishni yanada samarali bajarish imkoniyati paydo bo'ldi. Endi saqlash nuqtalarini o'rnatish mumkin - save points, va rollback() operatsiyasini chaqirganda, aniq saqlash nuqtasiga qaytish mumkin.

Saqlash uchun, save point yaratish kerak, bu buyruq orqali amalga oshiriladi:


   Savepoint save = connection.setSavepoint();

Saqlash nuqtasiga qaytish quyidagi buyruq yordamida amalga oshiriladi:


   connection.rollback(save);

Muammoli buyruq oldidan saqlash nuqtasini qo'shishga harakat qilamiz:


  try{
  	connection.setAutoCommit(false);

  	Statement statement = connection.createStatement();
  	int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
 
  	Savepoint save = connection.setSavepoint();
 	try{
      	int rowsCount3 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
 	}
 	catch (Exception e) {
    	connection.rollback(save);
 	}

	connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

Biz save-point qo'shib, muammoli metodini chaqirishdan oldin saqlash nuqtasini o'rnatib, va rollback(save) metodini chaqirib, saqlangan holatga qaytarib, zanjirli tranzaksiyalarni tashkil qildik.

Ha, bunday save/load o'yinlarda bo'ladi.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION