Mysql
 sql >> база данни >  >> RDS >> Mysql

Как правилно да използваме транзакции и ключалки, за да гарантираме целостта на базата данни?

Дотук добре, това най-малкото ще попречи на потребителя да извършва плащане в множество сесии (многократни опити за плащане на една и съща карта – добре да се справите с двойните щраквания.)

Как проверявате? Със стандартен SELECT или с SELECT ... FOR UPDATE ? Въз основа на стъпка 5 предполагам, че проверявате запазена колона за елемента или нещо подобно.

Проблемът тук е, че SELECT ... FOR UPDATE в стъпка 2 НЯМА да приложи FOR UPDATE заключете за всичко останало. Прилага се само за това, което е SELECT ed:cart-item маса. Въз основа на името, това ще бъде различен запис за всяка количка/потребител. Това означава, че други транзакции НЯМА да бъдат блокирани от продължаване.

Следвайки горното, въз основа на информацията, която сте предоставили, може да се окажете, че няколко души купуват един и същ артикул, ако не използвате SELECT ... FOR UPDATE на стъпка 3.

Предложено решение

  1. Започнете транзакцията
  2. SELECT ... FOR UPDATE cart-item маса.

Това ще блокира стартирането с двойно щракване. Това, което изберете тук, трябва да бъде някаква колона "поръчана количка". Ако направите това, втора транзакция ще спре тук и ще изчака първата да приключи и след това ще прочетете резултата, който първата е записала в базата данни.

Уверете се, че сте приключили процеса на плащане тук, ако cart-item таблицата казва, че вече е поръчана.

  1. SELECT ... FOR UPDATE таблицата, в която записвате, ако даден артикул е запазен.

Това ще заключи ДРУГИ колички/потребители от възможността да четат тези елементи.

Въз основа на резултата, ако артикулите не са запазени, продължете:

  1. UPDATE ... таблицата в стъпка 3, като маркирате елемента като запазен. Направете всяко друго INSERT s и UPDATE и вие имате нужда.

  2. Извършвам плащане. Извършете връщане назад, ако платежната услуга каже, че плащането не работи.

  3. Запишете плащането, ако е успешно.

  4. Извършете транзакция

Уверете се, че не правите нищо, което може да се провали между стъпки 5 и 7 (като изпращане на имейли), в противен случай може да се окажете те да направят плащане без то да бъде записано, в случай че транзакцията бъде отменена.

Стъпка 3 е важната стъпка по отношение на това да се уверите, че двама (или повече) души не се опитват да поръчат един и същ артикул. Ако двама души се опитат, вторият човек в крайна сметка ще "увисне", докато обработва първия. След това, когато първият приключи, вторият ще прочете колоната „резервирано“ и можете да върнете съобщение на потребителя, че някой вече е закупил този артикул.

Плащане в транзакция или не

Това е субективно. Обикновено искате да затваряте транзакциите възможно най-бързо, за да избегнете блокиране на взаимодействието на няколко души с базата данни наведнъж.

В този случай обаче наистина искате да изчакат. Въпросът е само колко време.

Ако решите да извършите транзакцията преди плащане, ще трябва да запишете напредъка си в някаква междинна таблица, да изпълните плащането и след това да запишете резултата. Имайте предвид, че ако плащането не успее, ще трябва ръчно да отмените записите за резервация на артикули, които сте актуализирали.

ИЗБЕРЕТЕ... ЗА АКТУАЛИЗИРАНЕ на несъществуващи редове

Само едно предупреждение, в случай че дизайнът на таблицата ви включва вмъкване на редове, където трябва по-рано SELECT ... FOR UPDATE :Ако ред не съществува, тази транзакция НЯМА да накара други транзакции да чакат, ако те също SELECT ... FOR UPDATE същия несъществуващ ред.

Така че, не забравяйте винаги да сериализирате заявките си, като правите SELECT ... FOR UPDATE на ред, за който знаете, че съществува първи. След това можете да SELECT ... FOR UPDATE на реда, който може да съществува или все още не съществува. (Не се опитвайте да правите само SELECT на реда, който може или не може да съществува, тъй като ще четете състоянието на реда в момента на стартиране на транзакцията, а не в момента, в който стартирате SELECT . И така, SELECT ... FOR UPDATE на несъществуващи редове все още е нещо, което трябва да направите, за да получите най-актуалната информация, само имайте предвид, че това няма да накара други транзакции да чакат.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. инструменти за тестване на натоварване на mysql

  2. Как работи функцията INSTR() в MySQL

  3. Entity Framework + MySQL - Защо производителността е толкова ужасна?

  4. Завършен Java проект, сега се създава jar или .exe файл (с база данни)

  5. PHP:PDO заявката не връща резултати, но същата заявка връща 4 резултата в phpmyadmin?