Halaman ini menjelaskan transaksi di Spanner dan memperkenalkan antarmuka transaksi DML terpartisi, hanya baca, dan baca-tulis Spanner.
Transaksi di Spanner adalah serangkaian operasi baca dan tulis yang dieksekusi secara atomik pada satu titik waktu logis di seluruh kolom, baris, dan tabel dalam database.
Sesi digunakan untuk melakukan transaksi di database Spanner. Sesi mewakili saluran komunikasi logis dengan layanan database Spanner. Sesi dapat menjalankan satu atau beberapa transaksi dalam satu waktu. Untuk mengetahui informasi selengkapnya, lihat Sesi.
Jenis transaksi
Spanner mendukung jenis transaksi berikut, yang masing-masing dirancang untuk pola interaksi data tertentu:
Baca-tulis: transaksi ini menggunakan penguncian pesimistis dan, jika diperlukan commit dua fase. Permintaan ini mungkin gagal dan memerlukan percobaan ulang. Meskipun terbatas pada satu database, pengguna dapat mengubah data di beberapa tabel dalam database tersebut.
Hanya baca: transaksi ini menjamin konsistensi data di beberapa operasi baca, tetapi tidak mengizinkan modifikasi data. Eksekusi dilakukan pada stempel waktu yang ditentukan sistem agar konsisten, atau pada stempel waktu sebelumnya yang dikonfigurasi pengguna. Tidak seperti transaksi baca-tulis, transaksi ini tidak memerlukan operasi commit atau penguncian, meskipun transaksi ini mungkin dijeda untuk menunggu operasi tulis yang sedang berlangsung selesai.
DML Terpartisi: jenis transaksi ini menjalankan pernyataan DML sebagai operasi DML terpartisi. API ini dioptimalkan untuk update dan penghapusan data skala besar, seperti pembersihan data atau penyisipan data massal. Untuk banyak operasi tulis yang tidak memerlukan transaksi atomik, pertimbangkan untuk menggunakan operasi tulis batch. Lihat Mengubah data menggunakan operasi tulis batch untuk mengetahui detailnya.
Transaksi baca-tulis
Gunakan transaksi baca-tulis yang mengunci untuk membaca, mengubah, dan menulis data secara atomik di mana pun dalam database. Jenis transaksi ini konsisten secara eksternal.
Minimalkan waktu transaksi aktif. Durasi transaksi yang lebih singkat
meningkatkan kemungkinan commit yang berhasil dan mengurangi pertentangan.
Spanner mencoba mempertahankan kunci baca tetap aktif selama transaksi terus melakukan pembacaan dan transaksi belum dihentikan melalui operasi
sessions.commit
atau
sessions.rollback
.
Jika klien tetap tidak aktif dalam jangka waktu yang lama, Spanner dapat melepaskan kunci transaksi dan membatalkan transaksi.
Secara konseptual, transaksi baca-tulis terdiri dari nol atau beberapa operasi baca atau pernyataan SQL
yang diikuti dengan sessions.commit
. Kapan saja sebelum sessions.commit
,
klien dapat mengirim permintaan sessions.rollback
untuk membatalkan transaksi.
Untuk melakukan operasi tulis yang bergantung pada satu atau beberapa operasi baca, gunakan transaksi baca-tulis yang mengunci:
- Jika Anda harus melakukan satu atau beberapa operasi tulis secara atomik, lakukan penulisan tersebut dalam transaksi baca-tulis yang sama. Misalnya, jika Anda mentransfer $200 dari akun A ke akun B, lakukan kedua operasi tulis (mengurangi akun A sebesar $200 dan menambah akun B sebesar $200) dan pembacaan saldo akun awal dalam transaksi yang sama.
- Jika Anda ingin menggandakan saldo akun A, lakukan operasi baca dan tulis dalam transaksi yang sama. Hal ini memastikan bahwa sistem membaca saldo sebelum sistem menggandakannya, lalu memperbaruinya.
- Jika Anda mungkin melakukan satu atau beberapa operasi tulis yang bergantung pada hasil dari satu atau beberapa operasi baca, lakukan penulisan dan pembacaan tersebut dalam transaksi baca-tulis yang sama, meskipun operasi tulis tidak dijalankan. Misalnya, jika Anda ingin mentransfer $200 dari akun A ke akun B hanya jika saldo saat ini akun A lebih besar dari $500, sertakan pembacaan saldo akun A dan operasi penulisan bersyarat dalam transaksi yang sama, meskipun transfer tidak terjadi.
Untuk melakukan operasi baca, gunakan metode baca tunggal atau transaksi hanya baca:
- Jika Anda hanya melakukan operasi baca, dan Anda dapat mengekspresikan operasi baca menggunakan satu metode baca, gunakan satu metode baca tersebut atau transaksi hanya baca. Tidak seperti transaksi baca-tulis, bacaan tunggal tidak memperoleh kunci.
Antarmuka
Library klien Spanner menyediakan antarmuka untuk mengeksekusi serangkaian tugas dalam transaksi baca-tulis, dengan percobaan ulang untuk pembatalan transaksi. Transaksi Spanner mungkin memerlukan beberapa kali percobaan ulang sebelum di-commit.
Beberapa situasi dapat menyebabkan pembatalan transaksi. Misalnya, jika dua transaksi mencoba mengubah data secara bersamaan, kebuntuan dapat terjadi. Dalam kasus seperti itu, Spanner akan membatalkan satu transaksi agar transaksi lainnya dapat dilanjutkan. Lebih jarang, peristiwa sementara dalam Spanner juga dapat menyebabkan pembatalan transaksi.
Karena transaksi bersifat atomik, transaksi yang dibatalkan tidak
memengaruhi database. Coba lagi transaksi dalam sesi yang sama untuk meningkatkan tingkat keberhasilan. Setiap percobaan ulang yang menghasilkan error ABORTED
akan meningkatkan
prioritas penguncian transaksi.
Saat menggunakan transaksi di library klien Spanner, Anda menentukan isi transaksi sebagai objek fungsi. Fungsi ini merangkum pembacaan dan penulisan yang dilakukan pada satu atau beberapa tabel database. Library klien Spanner menjalankan fungsi ini berulang kali hingga transaksi berhasil di-commit atau mengalami error yang tidak dapat dicoba ulang.
Contoh
Anggaplah Anda memiliki kolom MarketingBudget
dalam
tabel Albums
:
CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), MarketingBudget INT64 ) PRIMARY KEY (SingerId, AlbumId);
Departemen pemasaran Anda meminta Anda untuk memindahkan Rp2.000.000.000 dari anggaran Albums
(2, 2)
ke Albums (1, 1)
, tetapi hanya jika dana tersedia dalam anggaran album tersebut. Anda harus menggunakan transaksi baca-tulis yang mengunci untuk operasi ini,
karena transaksi dapat melakukan penulisan, bergantung pada hasil pembacaan.
Berikut cara menjalankan transaksi baca-tulis:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semantik
Bagian ini menjelaskan semantik untuk transaksi baca-tulis di Spanner.
Properti
Transaksi baca-tulis di Spanner menjalankan serangkaian operasi baca dan tulis secara atomik. Stempel waktu saat transaksi baca-tulis dieksekusi cocok dengan waktu yang telah berlalu. Urutan serialisasi cocok dengan urutan stempel waktu ini.
Transaksi baca-tulis menyediakan properti ACID database relasional. Transaksi baca-tulis Spanner menawarkan properti yang lebih kuat daripada ACID biasa.
Karena properti ini, sebagai developer aplikasi, Anda dapat berfokus pada kebenaran setiap transaksi dengan sendirinya, tanpa mengkhawatirkan cara melindungi eksekusinya dari transaksi lain yang mungkin dieksekusi pada saat yang sama.
Isolasi untuk transaksi baca-tulis
Setelah berhasil melakukan transaksi yang berisi serangkaian operasi baca dan tulis, Anda akan melihat hal berikut:
- Transaksi menampilkan nilai yang mencerminkan snapshot yang konsisten pada stempel waktu commit transaksi.
- Baris atau rentang kosong akan tetap kosong pada waktu penerapan.
- Transaksi meng-commit semua operasi tulis pada stempel waktu commit transaksi.
- Tidak ada transaksi yang dapat melihat penulisan hingga setelah transaksi di-commit.
Driver klien Spanner mencakup logika percobaan ulang transaksi yang menyembunyikan error sementara dengan menjalankan kembali transaksi dan memvalidasi data yang diamati klien.
Efeknya adalah semua operasi baca dan tulis tampak terjadi pada satu titik waktu, baik dari perspektif transaksi itu sendiri maupun dari perspektif pembaca dan penulis lain ke database Spanner. Artinya, operasi baca dan tulis terjadi pada stempel waktu yang sama. Sebagai contoh, lihat Serializability dan konsistensi eksternal.
Isolasi untuk transaksi baca
Saat transaksi baca-tulis hanya melakukan operasi baca, transaksi tersebut memberikan jaminan konsistensi yang serupa dengan transaksi hanya baca. Semua operasi baca dalam transaksi menampilkan data dari stempel waktu yang konsisten, termasuk konfirmasi baris yang tidak ada.
Salah satu perbedaannya adalah saat transaksi baca-tulis di-commit tanpa menjalankan operasi tulis. Dalam skenario ini, tidak ada jaminan bahwa data yang dibaca dalam transaksi tetap tidak berubah di database antara operasi baca dan commit transaksi.
Untuk memastikan keaktualan data dan memvalidasi bahwa data tidak dimodifikasi sejak pengambilan terakhir, pembacaan berikutnya diperlukan. Pembacaan ulang ini dapat dilakukan dalam transaksi baca-tulis lain atau dengan pembacaan yang kuat.
Untuk efisiensi yang optimal, jika transaksi hanya melakukan operasi baca, gunakan transaksi hanya baca, bukan transaksi baca-tulis.
Atomisitas, konsistensi, durabilitas
Selain isolasi, Spanner memberikan jaminan properti ACID lainnya:
- Atomisitas. Transaksi dianggap atomik jika semua operasinya berhasil diselesaikan, atau tidak ada sama sekali. Jika ada operasi dalam transaksi yang gagal, seluruh transaksi akan di-roll back ke status aslinya, sehingga memastikan integritas data.
- Konsistensi. Transaksi harus menjaga integritas aturan dan batasan database. Setelah transaksi selesai, database harus dalam keadaan valid, mematuhi aturan yang telah ditentukan.
- Ketahanan. Setelah transaksi di-commit, perubahannya akan disimpan secara permanen di database dan tetap ada jika terjadi kegagalan sistem, pemadaman listrik, atau gangguan lainnya.
Serialisabilitas dan konsistensi eksternal
Spanner menawarkan jaminan transaksional yang kuat, termasuk serialisabilitas dan konsistensi eksternal. Properti ini memastikan bahwa data tetap konsisten dan operasi terjadi dalam urutan yang dapat diprediksi, bahkan dalam lingkungan terdistribusi.
Serialisasi memastikan bahwa semua transaksi tampak dieksekusi satu demi satu dalam urutan tunggal dan berurutan, meskipun diproses secara bersamaan. Spanner mencapai hal ini dengan menetapkan stempel waktu commit ke transaksi, yang mencerminkan urutan commitnya.
Spanner memberikan jaminan yang lebih kuat yang dikenal sebagai konsistensi eksternal. Artinya, tidak hanya transaksi yang di-commit dalam urutan yang tercermin dalam stempel waktu commit-nya, tetapi stempel waktu ini juga selaras dengan waktu dunia nyata. Hal ini memungkinkan Anda membandingkan stempel waktu penerapan dengan waktu real-time, sehingga memberikan tampilan data yang konsisten dan diurutkan secara global.
Pada dasarnya, jika transaksi Txn1
di-commit sebelum transaksi Txn2
secara
real time, maka stempel waktu commit Txn1
lebih awal daripada stempel waktu
commit Txn2
.
Perhatikan contoh berikut:
Dalam skenario ini, selama linimasa t
:
- Transaksi
Txn1
membaca dataA
, melakukan penahapan penulisan keA
, lalu berhasil di-commit. - Transaksi
Txn2
dimulai setelahTxn1
dimulai. Membaca dataB
dan kemudian membaca dataA
.
Meskipun Txn2
dimulai sebelum Txn1 selesai, Txn2
mengamati perubahan yang dilakukan oleh Txn1
pada A
. Hal ini karena Txn2
membaca A
setelah Txn1
melakukan
operasi tulisnya ke A
.
Meskipun Txn1
dan Txn2
mungkin tumpang-tindih dalam waktu eksekusinya, stempel waktu commit, c1
dan c2
masing-masing, menerapkan urutan transaksi linear. Artinya:
- Semua operasi baca dan tulis dalam
Txn1
tampaknya terjadi pada satu titik waktu,c1
. - Semua operasi baca dan tulis dalam
Txn2
tampaknya terjadi pada satu titik waktu,c2
. - Yang penting,
c1
lebih awal daric2
untuk penulisan yang dilakukan, meskipun penulisan terjadi di mesin yang berbeda. JikaTxn2
hanya melakukan pembacaan,c1
lebih awal atau pada saat yang sama denganc2
.
Pengurutan yang kuat ini berarti bahwa jika operasi baca berikutnya mengamati efek Txn2
, operasi tersebut juga mengamati efek Txn1
. Properti ini bernilai benar (true) untuk semua transaksi yang berhasil di-commit.
Jaminan baca dan tulis saat transaksi gagal
Jika panggilan untuk mengeksekusi transaksi gagal, jaminan baca dan tulis yang Anda miliki bergantung pada error yang menyebabkan panggilan commit yang mendasarinya gagal.
Misalnya, error seperti "Baris Tidak Ditemukan" atau "Baris Sudah Ada" berarti penulisan mutasi yang di-buffer mengalami beberapa error, misalnya, baris yang coba diupdate oleh klien tidak ada. Dalam hal ini, operasi baca dijamin konsisten, operasi tulis tidak diterapkan, dan tidak adanya baris dijamin konsisten dengan operasi baca juga.
Jaminan baca dan tulis saat transaksi gagal
Jika transaksi Spanner gagal, jaminan yang Anda terima untuk operasi baca dan tulis bergantung pada error spesifik yang terjadi selama operasi commit
.
Misalnya, pesan error seperti "Baris Tidak Ditemukan" atau "Baris Sudah Ada" menunjukkan masalah selama penulisan mutasi yang di-buffer. Hal ini dapat terjadi jika, misalnya, baris yang coba diupdate oleh klien tidak ada. Dalam skenario ini:
- Pembacaan konsisten: Setiap data yang dibaca selama transaksi dijamin konsisten hingga titik error.
- Penulisan tidak diterapkan: Mutasi yang dicoba oleh transaksi tidak di-commit ke database.
- Konsistensi baris: Tidak adanya (atau status yang ada) baris yang memicu error konsisten dengan pembacaan yang dilakukan dalam transaksi.
Anda dapat membatalkan operasi baca asinkron di Spanner kapan saja tanpa memengaruhi operasi lain yang sedang berlangsung dalam transaksi yang sama. Fleksibilitas ini berguna jika operasi tingkat yang lebih tinggi dibatalkan, atau jika Anda memutuskan untuk membatalkan pembacaan berdasarkan hasil awal.
Namun, penting untuk dipahami bahwa permintaan pembatalan pembacaan tidak menjamin penghentiannya secara langsung. Setelah permintaan pembatalan, operasi baca mungkin masih:
- Berhasil diselesaikan: pembacaan mungkin selesai diproses dan menampilkan hasil sebelum pembatalan berlaku.
- Gagal karena alasan lain: pembacaan dapat dihentikan karena kesalahan lain, seperti pembatalan.
- Menampilkan hasil yang tidak lengkap: pembacaan dapat menampilkan hasil parsial, yang kemudian divalidasi sebagai bagian dari proses commit transaksi.
Perlu diperhatikan juga perbedaan dengan operasi commit
transaksi:
membatalkan commit
akan membatalkan seluruh transaksi, kecuali jika transaksi telah
di-commit atau gagal karena alasan lain.
Performa
Bagian ini menjelaskan masalah yang memengaruhi performa transaksi baca-tulis.
Kontrol konkurensi penguncian
Spanner mengizinkan beberapa klien berinteraksi dengan database yang sama secara bersamaan. Untuk menjaga konsistensi data di seluruh transaksi serentak ini, Spanner memiliki mekanisme penguncian yang menggunakan kunci bersama dan eksklusif.
Saat transaksi melakukan operasi baca, Spanner akan memperoleh kunci baca bersama pada data yang relevan. Kunci bersama ini memungkinkan operasi baca serentak lainnya mengakses data yang sama. Konkurensi ini dipertahankan hingga transaksi Anda bersiap untuk meng-commit perubahannya.
Selama fase commit, saat penulisan diterapkan, transaksi akan mencoba mengupgrade kuncinya menjadi kunci eksklusif. Untuk melakukannya, alat ini akan melakukan hal berikut:
- Memblokir permintaan kunci baca bersama baru pada data yang terpengaruh.
- Menunggu semua kunci baca bersama yang ada pada data tersebut dilepaskan.
- Setelah semua kunci baca bersama dihapus, kunci eksklusif akan ditempatkan, sehingga memberikan akses tunggal ke data selama penulisan.
Catatan tentang kunci:
- Granularitas: Spanner menerapkan penguncian pada granularitas baris dan kolom. Artinya, jika transaksi
T1
memegang kunci pada kolomA
barisalbumid
, transaksiT2
masih dapat menulis secara bersamaan ke kolomB
dari barisalbumid
yang sama tanpa konflik. - Penulisan tanpa pembacaan: Untuk penulisan tanpa pembacaan, Spanner tidak memerlukan kunci eksklusif. Sebagai gantinya, ia menggunakan kunci bersama penulis. Hal ini karena urutan penerapan untuk penulisan tanpa pembacaan ditentukan oleh stempel waktu penerapan, sehingga memungkinkan beberapa penulis beroperasi pada item yang sama secara bersamaan tanpa konflik. Penguncian eksklusif hanya diperlukan jika transaksi Anda pertama-tama membaca data yang akan ditulisnya.
- Indeks sekunder untuk pencarian baris: saat melakukan pencarian baris dalam transaksi baca-tulis, penggunaan indeks sekunder dapat meningkatkan performa secara signifikan. Dengan menggunakan indeks sekunder untuk membatasi baris yang dipindai ke rentang yang lebih kecil, Spanner mengunci lebih sedikit baris dalam tabel, sehingga memungkinkan modifikasi baris yang lebih bersamaan di luar rentang tertentu tersebut.
- Akses eksklusif resource eksternal: Kunci internal Spanner dirancang untuk konsistensi data dalam database Spanner itu sendiri. Jangan menggunakannya untuk menjamin akses eksklusif ke resource di luar Spanner. Spanner dapat membatalkan transaksi karena berbagai alasan, termasuk pengoptimalan sistem internal seperti pemindahan data di seluruh resource komputasi. Jika transaksi dicoba lagi (baik secara eksplisit oleh kode aplikasi Anda atau secara implisit oleh library klien seperti driver JDBC Spanner), kunci hanya dijamin telah dipegang selama upaya commit yang berhasil.
- Statistik kunci: untuk mendiagnosis dan menyelidiki konflik kunci dalam database Anda, Anda dapat menggunakan alat introspeksi Statistik kunci.
Deteksi kebuntuan
Spanner mendeteksi saat beberapa transaksi mungkin mengalami kebuntuan
dan memaksa semua transaksi kecuali satu transaksi untuk dibatalkan. Pertimbangkan skenario ini:
Txn1
memegang kunci pada rekaman A
dan menunggu kunci pada rekaman B
, sementara
Txn2
memegang kunci pada rekaman B
dan menunggu kunci pada rekaman A
. Untuk
mengatasi hal ini, salah satu transaksi harus dibatalkan, melepaskan kuncinya, dan
memungkinkan transaksi lainnya dilanjutkan.
Spanner menggunakan algoritma wound-wait standar untuk deteksi kebuntuan. Di balik layar, Spanner melacak usia setiap transaksi yang meminta kunci yang bertentangan. Hal ini memungkinkan transaksi lama membatalkan transaksi yang lebih baru. Transaksi lama adalah transaksi yang pembacaan, kueri, atau commit paling awalnya terjadi lebih awal.
Dengan memprioritaskan transaksi yang lebih lama, Spanner memastikan bahwa setiap transaksi pada akhirnya akan mendapatkan kunci setelah cukup lama untuk memiliki prioritas yang lebih tinggi. Misalnya, transaksi lama yang memerlukan kunci bersama penulis dapat membatalkan transaksi yang lebih baru yang memegang kunci bersama pembaca.
Eksekusi terdistribusi
Spanner dapat mengeksekusi transaksi pada data yang mencakup beberapa server, meskipun kemampuan ini memiliki biaya performa dibandingkan dengan transaksi server tunggal.
Jenis transaksi apa yang dapat didistribusikan? Spanner dapat mendistribusikan tanggung jawab untuk baris database di banyak server. Biasanya, baris dan baris tabel yang disisipkan yang sesuai dilayani oleh server yang sama, seperti dua baris dalam tabel yang sama dengan kunci yang berdekatan. Spanner dapat melakukan transaksi di seluruh baris pada server yang berbeda. Namun, sebagai aturan umum, transaksi yang memengaruhi banyak baris yang ditempatkan bersama lebih cepat dan lebih murah daripada transaksi yang memengaruhi banyak baris yang tersebar di seluruh database atau tabel besar.
Transaksi yang paling efisien di Spanner hanya mencakup operasi baca dan tulis yang harus diterapkan secara atomik. Transaksi akan berjalan paling cepat jika semua pembacaan dan penulisan mengakses data di bagian ruang kunci yang sama.
Transaksi hanya baca
Selain mengunci transaksi baca-tulis, Spanner menawarkan transaksi hanya baca.
Gunakan transaksi hanya baca saat Anda perlu menjalankan lebih dari satu operasi baca pada stempel waktu yang sama. Jika Anda dapat mengekspresikan pembacaan menggunakan salah satu metode pembacaan tunggal Spanner, Anda harus menggunakan metode pembacaan tunggal tersebut. Performa penggunaan satu panggilan baca tersebut seharusnya sebanding dengan performa satu baca yang dilakukan dalam transaksi baca saja.
Jika Anda membaca data dalam jumlah besar, pertimbangkan untuk menggunakan partisi guna membaca data secara paralel.
Karena transaksi hanya baca tidak menulis, transaksi tersebut tidak memegang kunci dan tidak memblokir transaksi lain. Transaksi hanya baca mengamati awalan yang konsisten dari histori commit transaksi, sehingga aplikasi Anda selalu mendapatkan data yang konsisten.
Antarmuka
Spanner menyediakan antarmuka untuk mengeksekusi serangkaian tugas dalam konteks transaksi hanya baca, dengan percobaan ulang untuk pembatalan transaksi.
Contoh
Contoh berikut menunjukkan cara menggunakan transaksi hanya baca untuk mendapatkan data yang konsisten untuk dua pembacaan pada stempel waktu yang sama:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semantik
Bagian ini menjelaskan semantik untuk transaksi hanya baca.
Transaksi hanya baca snapshot
Saat transaksi hanya baca dieksekusi di Spanner, transaksi tersebut melakukan semua pembacaannya pada satu titik waktu logis. Artinya, transaksi hanya baca dan pembaca serta penulis serentak lainnya melihat snapshot database yang konsisten pada saat tertentu.
Transaksi hanya baca snapshot ini menawarkan pendekatan yang lebih sederhana untuk pembacaan yang konsisten dibandingkan dengan transaksi baca-tulis penguncian. Berikut alasannya:
- Tanpa kunci: transaksi hanya baca tidak memperoleh kunci. Sebagai gantinya, opsi tersebut beroperasi dengan memilih stempel waktu Spanner dan menjalankan semua operasi baca terhadap versi historis data tersebut. Karena tidak menggunakan kunci, batch tidak akan memblokir transaksi baca-tulis serentak.
- Tidak ada pembatalan: transaksi ini tidak pernah dibatalkan. Meskipun dapat gagal jika stempel waktu baca yang dipilihnya dikumpulkan sampah, kebijakan pengumpulan sampah default Spanner biasanya cukup besar sehingga sebagian besar aplikasi tidak akan mengalami masalah ini.
- Tidak ada commit atau roll back: transaksi hanya baca tidak memerlukan panggilan ke
sessions.commit
atausessions.rollback
dan sebenarnya dicegah untuk melakukannya.
Untuk menjalankan transaksi snapshot, klien menentukan batas stempel waktu, yang menginstruksikan Spanner cara memilih stempel waktu baca. Jenis batas stempel waktu mencakup:
- Pembacaan yang andal: pembacaan ini menjamin bahwa Anda akan melihat efek semua transaksi yang dilakukan sebelum pembacaan dimulai. Semua baris dalam satu pembacaan konsisten. Namun, pembacaan kuat tidak dapat diulang, meskipun pembacaan kuat menampilkan stempel waktu, dan pembacaan lagi pada stempel waktu yang sama dapat diulang. Dua transaksi hanya baca yang kuat secara berurutan dapat menghasilkan hasil yang berbeda karena penulisan serentak. Kueri pada aliran perubahan harus menggunakan batas ini. Untuk mengetahui detail selengkapnya, lihat TransactionOptions.ReadOnly.strong.
- Keterlambatan yang tepat: opsi ini menjalankan pembacaan pada stempel waktu yang Anda tentukan, baik sebagai stempel waktu absolut atau sebagai durasi keterlambatan relatif terhadap waktu saat ini. Hal ini memastikan Anda mengamati awalan yang konsisten dari histori transaksi global hingga stempel waktu tersebut dan memblokir transaksi yang bertentangan yang mungkin di-commit dengan stempel waktu yang kurang dari atau sama dengan stempel waktu baca. Meskipun sedikit lebih cepat daripada mode keusangan terbatas, mode ini dapat menampilkan data yang lebih lama. Untuk mengetahui detail selengkapnya, lihat TransactionOptions.ReadOnly.read_timestamp dan TransactionOptions.ReadOnly.exact_staleness.
- Keterlambatan yang dibatasi: Spanner memilih stempel waktu terbaru dalam batas keterlambatan yang ditentukan pengguna, sehingga memungkinkan eksekusi di replika terdekat yang tersedia tanpa pemblokiran. Semua baris yang ditampilkan konsisten. Seperti pembacaan kuat, keusangan terbatas tidak dapat diulang, karena pembacaan yang berbeda mungkin dieksekusi pada stempel waktu yang berbeda meskipun dengan batas yang sama. Operasi baca ini beroperasi dalam dua fase (negosiasi stempel waktu, lalu baca) dan biasanya sedikit lebih lambat daripada keusangan tepat, tetapi sering kali menampilkan hasil yang lebih baru dan lebih mungkin dieksekusi di replika lokal. Mode ini hanya tersedia untuk transaksi hanya baca sekali pakai karena negosiasi stempel waktu mengharuskan mengetahui baris mana yang akan dibaca sebelumnya. Untuk detail selengkapnya, lihat TransactionOptions.ReadOnly.max_staleness dan TransactionOptions.ReadOnly.min_read_timestamp.
Transaksi DML yang dipartisi
Anda dapat menggunakan DML berpartisi untuk mengeksekusi pernyataan UPDATE
dan DELETE
skala besar tanpa mengalami batas transaksi atau mengunci seluruh tabel. Spanner mencapai hal ini dengan
mempartisi ruang kunci dan menjalankan pernyataan DML pada setiap partisi
dalam transaksi baca-tulis terpisah.
Untuk menggunakan DML yang tidak dipartisi, Anda menjalankan pernyataan dalam transaksi baca-tulis yang Anda buat secara eksplisit dalam kode Anda. Untuk mengetahui detail selengkapnya, lihat Menggunakan DML.
Antarmuka
Spanner menyediakan antarmuka TransactionOptions.partitionedDml untuk menjalankan satu pernyataan DML terpartisi.
Contoh
Contoh kode berikut mengupdate kolom MarketingBudget
dari tabel Albums
.
C++
Anda menggunakan fungsi ExecutePartitionedDml()
untuk menjalankan pernyataan DML berpartisi.
C#
Anda menggunakan metode ExecutePartitionedUpdateAsync()
untuk menjalankan pernyataan DML berpartisi.
Go
Anda menggunakan metode PartitionedUpdate()
untuk menjalankan pernyataan DML berpartisi.
Java
Anda menggunakan metode executePartitionedUpdate()
untuk menjalankan pernyataan DML berpartisi.
Node.js
Anda menggunakan metode runPartitionedUpdate()
untuk menjalankan pernyataan DML berpartisi.
PHP
Anda menggunakan metode executePartitionedUpdate()
untuk menjalankan pernyataan DML berpartisi.
Python
Anda menggunakan metode execute_partitioned_dml()
untuk menjalankan pernyataan DML berpartisi.
Ruby
Anda menggunakan metode execute_partitioned_update()
untuk menjalankan pernyataan DML berpartisi.
Contoh kode berikut menghapus baris dari tabel Singers
, berdasarkan kolom
SingerId
.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semantik
Bagian ini menjelaskan semantik untuk DML yang dipartisi.
Memahami eksekusi DML yang dipartisi
Anda hanya dapat menjalankan satu pernyataan DML yang dipartisi dalam satu waktu, baik Anda menggunakan metode library klien maupun Google Cloud CLI.
Transaksi yang dipartisi tidak mendukung commit atau rollback. Spanner akan segera mengeksekusi dan menerapkan pernyataan DML. Jika Anda membatalkan operasi, atau operasi gagal, Spanner akan membatalkan semua partisi yang sedang dieksekusi dan tidak memulai partisi yang tersisa. Namun, Spanner tidak mengembalikan partisi yang telah dieksekusi.
Strategi perolehan kunci DML yang dipartisi
Untuk mengurangi pertentangan kunci, DML berpartisi hanya memperoleh kunci baca pada baris yang cocok dengan klausa WHERE
. Transaksi independen yang lebih kecil yang digunakan untuk setiap
partisi juga memegang kunci untuk waktu yang lebih singkat.
Batas transaksi sesi
Setiap sesi di Spanner dapat memiliki satu transaksi aktif dalam satu waktu. Hal ini mencakup pembacaan dan kueri mandiri, yang secara internal menggunakan transaksi dan diperhitungkan dalam batas ini. Setelah transaksi selesai, sesi dapat segera digunakan kembali untuk transaksi berikutnya; sesi baru tidak perlu dibuat untuk setiap transaksi.
Stempel waktu baca lama dan pembersihan sampah memori versi
Spanner melakukan pembersihan sampah memori versi untuk mengumpulkan data yang dihapus atau ditimpa dan mengklaim kembali penyimpanan. Secara default, data yang lebih lama dari satu jam akan diklaim ulang. Spanner tidak dapat melakukan pembacaan pada stempel waktu yang lebih lama dari VERSION_RETENTION_PERIOD
yang dikonfigurasi, yang secara default adalah satu jam, tetapi dapat dikonfigurasi hingga satu minggu. Jika pembacaan menjadi terlalu lama selama eksekusi, pembacaan tersebut akan gagal dan menampilkan error FAILED_PRECONDITION
.
Kueri pada aliran perubahan
Aliran perubahan adalah objek skema yang dapat Anda konfigurasi untuk memantau modifikasi data di seluruh database, tabel tertentu, atau sekumpulan kolom yang ditentukan dalam database.
Saat Anda membuat aliran data perubahan, Spanner akan menentukan
fungsi bernilai tabel (TVF) SQL yang sesuai. Anda dapat menggunakan TVF ini untuk membuat kueri
catatan perubahan di aliran perubahan terkait dengan
metode sessions.executeStreamingSql
. Nama TVF dibuat dari nama aliran perubahannya dan selalu
dimulai dengan READ_
.
Semua kueri pada TVF aliran perubahan harus dieksekusi menggunakan
sessions.executeStreamingSql
API dalam transaksi hanya baca sekali pakai
dengan timestamp_bound
hanya baca yang kuat. TVF aliran perubahan memungkinkan Anda
menentukan start_timestamp
dan end_timestamp
untuk rentang waktu. Semua catatan perubahan dalam periode retensi dapat diakses menggunakan timestamp_bound
hanya baca yang kuat ini. Semua
TransactionOptions
lainnya
tidak valid untuk kueri aliran perubahan.
Selain itu, jika
TransactionOptions.read_only.return_read_timestamp
disetel ke true
, pesan
Transaction
yang menjelaskan
transaksi akan menampilkan nilai khusus 2^63 - 2
, bukan stempel waktu
baca yang valid. Anda harus menghapus nilai khusus ini dan tidak menggunakannya untuk kueri berikutnya.
Untuk mengetahui informasi selengkapnya, lihat Alur kerja kueri aliran perubahan.
Transaksi Tidak Aktif
Transaksi dianggap tidak aktif jika tidak memiliki pembacaan atau kueri SQL yang belum selesai
dan belum memulai satu pun dalam 10 detik terakhir. Spanner dapat membatalkan transaksi yang tidak aktif untuk mencegahnya menahan kunci tanpa batas. Jika transaksi
yang tidak aktif dibatalkan, commit akan gagal dan menampilkan error ABORTED
.
Menjalankan kueri kecil secara berkala, seperti SELECT 1
, dalam transaksi dapat mencegahnya menjadi tidak aktif.