Contoh semantik transaksi Neptunus - Amazon Neptune

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Contoh semantik transaksi Neptunus

Contoh berikut menggambarkan kasus penggunaan yang berbeda untuk semantik transaksi di Amazon Neptune.

Contoh 1 - Memasukkan Properti Hanya Jika Tidak Ada

Misalkan Anda ingin memastikan bahwa properti diatur hanya sekali. Sebagai contoh, misalkan beberapa kueri mencoba untuk menetapkan kepada seseorang skor kredit secara bersamaan. Anda hanya ingin satu instans dari properti dimasukkan, dan kueri lainnya gagal karena properti telah ditetapkan.

# GREMLIN: g.V('person1').hasLabel('Person').coalesce(has('creditScore'), property('creditScore', 'AAA+')) # SPARQL: INSERT { :person1 :creditScore "AAA+" .} WHERE { :person1 rdf:type :Person . FILTER NOT EXISTS { :person1 :creditScore ?o .} }

Langkah property() Gremlin menyisipkan properti dengan kunci dan nilai yang diberikan. Langkah coalesce() mengeksekusi argumen pertama di langkah pertama, dan jika gagal, maka mengeksekusi langkah kedua:

Sebelum memasukkan nilai properti creditScore untuk vertex person1 yang diberikan, transaksi harus coba membaca kemungkinan tidak adanya nilai creditScore untuk person1. Ini mencoba membaca kunci rentang SP untuk S=person1 dan P=creditScore dalam SPOG indeks tempat nilai creditScore ada atau akan ditulis.

Mengambil kunci rentang ini mencegah transaksi bersamaan apapun dari memasukkan nilai creditScore secara bersamaan. Ketika ada beberapa transaksi paralel, paling banyak salah satu dari transaksi tersebut dapat memperbarui nilai pada suatu waktu. Ini mengeliminasi anomali lebih dari satu properti creditScore yang dibuat.

Contoh 2 - Menegaskan Bahwa Nilai Properti Adalah Unik secara Global

Misalkan Anda ingin memasukkan seseorang dengan nomor Jaminan Sosial sebagai kunci utama. Anda ingin kueri mutasi Anda menjamin bahwa, pada tingkat global, tidak ada orang lain dalam database memiliki nomor Jaminan Sosial yang sama:

# GREMLIN: g.V().has('ssn', 123456789).fold() .coalesce(__.unfold(), __.addV('Person').property('name', 'John Doe').property('ssn', 123456789')) # SPARQL: INSERT { :person1 rdf:type :Person . :person1 :name "John Doe" . :person1 :ssn 123456789 .} WHERE { FILTER NOT EXISTS { ?person :ssn 123456789 } }

Contoh ini sama dengan yang sebelumnya. Perbedaan utamanya adalah bahwa kunci rentang diambil pada indeks POGS ketimbang indeks SPOG.

Transaksi mengeksekusi kueri harus membaca pola, ?person :ssn 123456789, di mana posisi P dan O terikat. Kunci rentang diambil pada indeks POGS untuk P=ssn dan O=123456789.

  • Jika pola itu ada, tidak ada tindakan yang diambil.

  • Jika tidak ada, penguncian mencegah setiap transaksi bersamaan dari menyisipkan nomor Jaminan Sosial juga

Contoh 3 - Mengubah Properti Jika Properti Lain Memiliki Nilai Tertentu

Misalkan berbagai peristiwa dalam game memindahkan seseorang dari tingkat satu ke tingkat dua, dan menugaskan mereka properti level2Score baru yang diatur ke nol. Anda harus yakin bahwa beberapa instans yang bersamaan dari transaksi tersebut tidak dapat membuat beberapa instans dari properti skor tingkat-dua. Kueri di Gremlin dan SPARQL mungkin terlihat seperti berikut ini.

# GREMLIN: g.V('person1').hasLabel('Person').has('level', 1) .property('level2Score', 0) .property(Cardinality.single, 'level', 2) # SPARQL: DELETE { :person1 :level 1 .} INSERT { :person1 :level2Score 0 . :person1 :level 2 .} WHERE { :person1 rdf:type :Person . :person1 :level 1 .}

Di Gremlin, ketika Cardinality.single ditentukan, langkah property() menambahkan properti baru atau menggantikan nilai properti yang ada dengan nilai baru yang ditentukan.

Setiap pembaruan ke nilai properti, seperti meningkatkan level dari 1 sampai 2, diimplementasikan sebagai penghapusan catatan saat ini dan penyisipan catatan baru dengan nilai properti baru. Dalam hal ini, catatan dengan tingkat nomor 1 dihapus dan catatan dengan tingkat nomor 2 dimasukkan kembali.

Untuk transaksi agar dapat menambah level2Score dan memperbarui level dari 1 sampai 2, transaksi harus terlebih dahulu memvalidasi bahwa nilai level saat ini sama dengan 1. Dengan demikian, dibutuhkan kunci rentang pada prefiks SPO untuk S=person1, P=level, dan O=1 dalam indeks SPOG. Kunci ini mencegah transaksi yang bersamaan menghapus versi 1 tiga kali lipat, dan sebagai hasilnya, tidak ada pembaruan bersamaan yang bertentangan dapat terjadi.

Contoh 4 - Mengganti Properti yang Ada

Peristiwa tertentu dapat memperbarui nilai kredit seseorang ke nilai baru (di sini BBB). Tetapi Anda ingin memastikan bahwa peristiwa bersamaan dari jenis tersebut tidak dapat membuat beberapa properti skor kredit untuk seseorang.

# GREMLIN: g.V('person1').hasLabel('Person') .sideEffect(properties('creditScore').drop()) .property('creditScore', 'BBB') # SPARQL: DELETE { :person1 :creditScore ?o .} INSERT { :person1 :creditScore "BBB" .} WHERE { :person1 rdf:type :Person . :person1 :creditScore ?o .}

Kasus ini mirip dengan contoh 3, kecuali bahwa alih-alih mengunci SPO awalan, Neptunus mengunci SP awalan dengan dan hanya. S=person1 P=creditScore Hal ini mencegah transaksi bersamaan dari memasukkan atau menghapus setiap triple dengan properti creditScore untuk subjek person1.

Contoh 5 - Menghindari Properti atau Edge Menggantung

Pembaruan pada entitas tidak harus meninggalkan elemen menggantung, yaitu properti atau edge yang terkait dengan entitas yang tidak diketik. Ini hanya masalahSPARQL, karena Gremlin memiliki batasan bawaan untuk mencegah elemen menggantung.

# SPARQL: tx1: INSERT { :person1 :age 23 } WHERE { :person1 rdf:type :Person } tx2: DELETE { :person1 ?p ?o }

Kueri INSERT harus membaca dan mengunci prefiks SPO dengan S=person1, P=rdf:type, dan O=Person dalam indeks SPOG. Penguncian mencegah kueri DELETE dari berhasilnya secara paralel.

Dalam perlombaan antara query DELETE mencoba untuk menghapus rekaman :person1 rdf:type :Person dan query INSERT membaca catatan dan membuat kunci rentang di SPO dalam Indeks SPOG, hasil berikut ini mungkin:

  • Jika kueri INSERT melakukan sebelum kueri DELETE membaca dan menghapus semua catatan untuk :person1, :person1 dihapus seluruhnya dari database, termasuk catatan yang baru dimasukkan.

  • Jika query DELETE melakukan sebelum kueri INSERT coba membaca catatan :person1 rdf:type :Person, pembacaan mengamati perubahan yang dilakukan. Artinya, tidak menemukan catatan :person1 rdf:type :Person apapun dan karenanya menjadi no-op.

  • Jika INSERT kueri dibaca sebelum DELETE kueri dilakukan, :person1 rdf:type :Person triple dikunci dan DELETE kueri diblokir hingga INSERT kueri dilakukan, seperti pada kasus pertama sebelumnya.

  • Jika bacaan DELETE membaca sebelum kueri INSERT, dan kueri INSERT mencoba untuk membaca dan mengunci prefiks SPO untuk catatan, maka konflik terdeteksi. Hal ini karena triple telah ditandai untuk dihapus, dan INSERT kemudian gagal.

Dalam semua urutan kemungkinan yang berbeda dari peristiwa ini, tidak ada edge menggantung dibuat.