Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana cara menggunakan transaksi dan kunci dengan benar untuk memastikan integritas basis data?

Sejauh ini bagus, ini setidaknya akan mencegah pengguna melakukan checkout dalam beberapa sesi (berkali-kali mencoba checkout kartu yang sama - bagus untuk menangani klik ganda.)

Bagaimana Anda memeriksa? Dengan standar SELECT atau dengan SELECT ... FOR UPDATE ? Berdasarkan langkah 5, saya kira Anda memeriksa kolom yang dipesan pada item, atau yang serupa.

Masalahnya di sini adalah bahwa SELECT ... FOR UPDATE pada langkah 2 TIDAK akan menerapkan FOR UPDATE mengunci segala sesuatu yang lain. Itu hanya berlaku untuk apa yang SELECT ed:cart-item meja. Berdasarkan namanya, itu akan menjadi catatan yang berbeda untuk setiap keranjang/pengguna. Ini berarti bahwa transaksi lain TIDAK akan diblokir untuk melanjutkan.

Mengikuti di atas, berdasarkan informasi yang Anda berikan, Anda mungkin berakhir dengan beberapa orang membeli item yang sama, jika Anda tidak menggunakan SELECT ... FOR UPDATE pada langkah 3.

Solusi yang Disarankan

  1. Mulai transaksi
  2. SELECT ... FOR UPDATE cart-item tabel.

Ini akan mengunci klik dua kali agar tidak berjalan. Apa yang Anda pilih di sini harus menjadi semacam kolom "pesanan keranjang". Jika Anda melakukan ini, transaksi kedua akan berhenti di sini dan menunggu yang pertama selesai, lalu membaca hasilnya apa yang pertama disimpan ke database.

Pastikan untuk mengakhiri proses checkout di sini jika cart-item tabel mengatakan sudah dipesan.

  1. SELECT ... FOR UPDATE tabel tempat Anda mencatat jika suatu item telah dipesan.

Ini akan mengunci troli/pengguna LAIN agar tidak dapat membaca item tersebut.

Berdasarkan hasil, jika barang tidak dipesan, lanjutkan:

  1. UPDATE ... tabel di langkah 3, menandai item sebagai dipesan. Lakukan INSERT lainnya s dan UPDATE yang Anda butuhkan juga.

  2. Melakukan pembayaran. Lakukan rollback jika layanan pembayaran mengatakan pembayaran tidak berhasil.

  3. Catat pembayaran, jika berhasil.

  4. Lakukan transaksi

Pastikan Anda tidak melakukan apa pun yang mungkin gagal antara langkah 5 dan 7 (seperti mengirim email), jika tidak, Anda mungkin berakhir dengan mereka melakukan pembayaran tanpa dicatat, jika transaksi dibatalkan.

Langkah 3 adalah langkah penting untuk memastikan dua (atau lebih) orang tidak mencoba memesan barang yang sama. Jika dua orang mencoba, orang kedua akan membuat halaman web mereka "hang" saat memproses yang pertama. Kemudian ketika yang pertama selesai, yang kedua akan membaca kolom "reserved", dan Anda dapat mengembalikan pesan kepada pengguna bahwa seseorang telah membeli item tersebut.

Pembayaran dalam transaksi atau tidak

Ini subjektif. Umumnya, Anda ingin menutup transaksi secepat mungkin, untuk menghindari beberapa orang terkunci dari interaksi dengan database sekaligus.

Namun, dalam kasus ini, Anda sebenarnya ingin mereka menunggu. Ini hanya masalah berapa lama.

Jika Anda memilih untuk melakukan transaksi sebelum pembayaran, Anda harus mencatat kemajuan Anda di beberapa tabel perantara, menjalankan pembayaran, dan kemudian mencatat hasilnya. Ketahuilah bahwa jika pembayaran gagal, Anda harus secara manual membatalkan catatan reservasi item yang Anda perbarui.

PILIH ... UNTUK PEMBARUAN pada baris yang tidak ada

Sekedar peringatan, jika desain tabel Anda melibatkan penyisipan baris di mana Anda perlu SELECT ... FOR UPDATE sebelumnya :Jika baris tidak ada, transaksi tersebut TIDAK akan menyebabkan transaksi lain menunggu, jika mereka juga SELECT ... FOR UPDATE baris yang sama tidak ada.

Jadi, pastikan untuk selalu membuat serial permintaan Anda dengan melakukan SELECT ... FOR UPDATE pada baris yang Anda tahu ada terlebih dahulu. Kemudian Anda dapat SELECT ... FOR UPDATE pada baris yang mungkin atau mungkin belum ada. (Jangan mencoba melakukan SELECT pada baris yang mungkin atau mungkin tidak ada, karena Anda akan membaca status baris pada saat transaksi dimulai, bukan pada saat Anda menjalankan SELECT . Jadi, SELECT ... FOR UPDATE pada baris yang tidak ada masih merupakan sesuatu yang perlu Anda lakukan untuk mendapatkan informasi terbaru, perlu diketahui bahwa itu tidak akan menyebabkan transaksi lain menunggu.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ubah nama tabel menjadi huruf besar

  2. Kueri SUM untuk dua bidang dalam dua tabel yang berbeda

  3. Cara Menampilkan Proses MySQL

  4. 1064 kesalahan dalam CREATE TABLE ... TYPE=MYISAM

  5. org.hibernate.InstantiationException:Tidak ada konstruktor default untuk entitas::principal.Cliente