Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Apakah pembaruan SQL akan memengaruhi subquery-nya selama pembaruan dijalankan?

** Diedit **

Memilih dari tabel target

Dari 13.2.9.8. Subquery dalam FROM Clause:

Subquery dalam klausa FROM dapat mengembalikan skalar, kolom, baris, atau tabel. Subquery dalam klausa FROM tidak dapat dikorelasikan dengan subquery, kecuali jika digunakan dalam klausa ON dari operasi JOIN.

Jadi, ya, Anda dapat melakukan kueri di atas.

Masalahnya

Sebenarnya ada dua masalah di sini. Ada konkurensi, atau memastikan bahwa tidak ada orang lain yang mengubah data dari bawah kaki kita. Ini ditangani dengan penguncian. Menangani modifikasi aktual dari nilai baru versus nilai lama ditangani dengan tabel turunan.

Mengunci

Dalam kasus kueri Anda di atas, dengan InnoDB, MySQL melakukan SELECT terlebih dahulu, dan memperoleh kunci baca (bersama) pada setiap baris dalam tabel satu per satu. Jika Anda memiliki klausa WHERE dalam pernyataan SELECT, maka hanya record yang Anda pilih yang akan dikunci, di mana rentang akan menyebabkan celah dikunci juga.

Kunci baca mencegah kueri lain memperoleh kunci tulis, sehingga catatan tidak dapat diperbarui dari tempat lain saat sedang dibaca terkunci.

Kemudian, MySQL memperoleh kunci tulis (eksklusif) pada setiap catatan dalam tabel secara individual. Jika Anda memiliki klausa WHERE dalam pernyataan UPDATE, maka hanya catatan tertentu yang akan dikunci, dan sekali lagi, jika klausa WHERE memilih rentang, rentang akan dikunci.

Catatan apa pun yang memiliki kunci baca dari SELECT sebelumnya akan secara otomatis dieskalasi menjadi kunci tulis.

Kunci tulis mencegah kueri lain mendapatkan kunci baca atau tulis.

Anda dapat menggunakan Innotop untuk melihat ini dengan menjalankannya dalam mode Kunci, memulai transaksi, menjalankan kueri (tetapi jangan melakukan itu), dan Anda akan melihat kunci di Innotop. Anda juga dapat melihat detail tanpa Innotop dengan SHOW ENGINE INNODB STATUS .

Kebuntuan

Kueri Anda rentan terhadap kebuntuan jika dua instans dijalankan secara bersamaan. Jika kueri A mendapat kunci baca, lalu kueri B mendapat kunci baca, kueri A harus menunggu kunci baca kueri B dirilis sebelum dapat memperoleh kunci tulis. Namun, kueri B tidak akan melepaskan kunci baca sampai setelah selesai, dan tidak akan selesai kecuali dapat memperoleh kunci tulis. Kueri A dan kueri B menemui jalan buntu, dan karenanya, menemui jalan buntu.

Oleh karena itu, Anda mungkin ingin melakukan penguncian tabel eksplisit, baik untuk menghindari penguncian data dalam jumlah besar (yang menggunakan memori dan memengaruhi kinerja), dan untuk menghindari kebuntuan.

Pendekatan alternatif adalah dengan menggunakan SELECT ... FOR UPDATE pada SELECT batin Anda. Ini dimulai dengan kunci tulis di semua baris alih-alih dimulai dengan membaca dan mengeskalasinya.

Tabel turunan

Untuk SELECT dalam, MySQL membuat tabel sementara yang diturunkan. Tabel turunan adalah salinan sebenarnya yang tidak diindeks dari data yang berada di tabel sementara yang dibuat secara otomatis oleh MySQL (sebagai lawan dari tabel sementara yang Anda buat secara eksplisit dan dapat ditambahkan indeks).

Karena MySQL menggunakan tabel turunan, itulah nilai lama sementara yang Anda rujuk dalam pertanyaan Anda. Dengan kata lain, tidak ada keajaiban di sini. MySQL melakukannya sama seperti Anda melakukannya di tempat lain, dengan nilai sementara.

Anda dapat melihat tabel turunan dengan melakukan EXPLAIN terhadap pernyataan UPDATE Anda (didukung di MySQL 5.6+).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Memasukkan beberapa baris dengan urutan di Oracle

  2. Bagaimana cara menggunakan CREATE OR REPLACE?

  3. Apa sebenarnya yang dilakukan tanda kutip di sekitar nama tabel?

  4. Pengembang Oracle SQL - Cara Memulihkan Tabel yang Dijatuhkan

  5. Paksa Oracle Jatuhkan Tabel Temp Global