1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 import org.rocksdb.*; 7 8 import static java.nio.charset.StandardCharsets.UTF_8; 9 10 /** 11 * Demonstrates using Transactions on a TransactionDB with 12 * varying isolation guarantees 13 */ 14 public class TransactionSample { 15 private static final String dbPath = "/tmp/rocksdb_transaction_example"; 16 main(final String args[])17 public static final void main(final String args[]) throws RocksDBException { 18 19 try(final Options options = new Options() 20 .setCreateIfMissing(true); 21 final TransactionDBOptions txnDbOptions = new TransactionDBOptions(); 22 final TransactionDB txnDb = 23 TransactionDB.open(options, txnDbOptions, dbPath)) { 24 25 try (final WriteOptions writeOptions = new WriteOptions(); 26 final ReadOptions readOptions = new ReadOptions()) { 27 28 //////////////////////////////////////////////////////// 29 // 30 // Simple Transaction Example ("Read Committed") 31 // 32 //////////////////////////////////////////////////////// 33 readCommitted(txnDb, writeOptions, readOptions); 34 35 36 //////////////////////////////////////////////////////// 37 // 38 // "Repeatable Read" (Snapshot Isolation) Example 39 // -- Using a single Snapshot 40 // 41 //////////////////////////////////////////////////////// 42 repeatableRead(txnDb, writeOptions, readOptions); 43 44 45 //////////////////////////////////////////////////////// 46 // 47 // "Read Committed" (Monotonic Atomic Views) Example 48 // --Using multiple Snapshots 49 // 50 //////////////////////////////////////////////////////// 51 readCommitted_monotonicAtomicViews(txnDb, writeOptions, readOptions); 52 } 53 } 54 } 55 56 /** 57 * Demonstrates "Read Committed" isolation 58 */ readCommitted(final TransactionDB txnDb, final WriteOptions writeOptions, final ReadOptions readOptions)59 private static void readCommitted(final TransactionDB txnDb, 60 final WriteOptions writeOptions, final ReadOptions readOptions) 61 throws RocksDBException { 62 final byte key1[] = "abc".getBytes(UTF_8); 63 final byte value1[] = "def".getBytes(UTF_8); 64 65 final byte key2[] = "xyz".getBytes(UTF_8); 66 final byte value2[] = "zzz".getBytes(UTF_8); 67 68 // Start a transaction 69 try(final Transaction txn = txnDb.beginTransaction(writeOptions)) { 70 // Read a key in this transaction 71 byte[] value = txn.get(readOptions, key1); 72 assert(value == null); 73 74 // Write a key in this transaction 75 txn.put(key1, value1); 76 77 // Read a key OUTSIDE this transaction. Does not affect txn. 78 value = txnDb.get(readOptions, key1); 79 assert(value == null); 80 81 // Write a key OUTSIDE of this transaction. 82 // Does not affect txn since this is an unrelated key. 83 // If we wrote key 'abc' here, the transaction would fail to commit. 84 txnDb.put(writeOptions, key2, value2); 85 86 // Commit transaction 87 txn.commit(); 88 } 89 } 90 91 /** 92 * Demonstrates "Repeatable Read" (Snapshot Isolation) isolation 93 */ repeatableRead(final TransactionDB txnDb, final WriteOptions writeOptions, final ReadOptions readOptions)94 private static void repeatableRead(final TransactionDB txnDb, 95 final WriteOptions writeOptions, final ReadOptions readOptions) 96 throws RocksDBException { 97 98 final byte key1[] = "ghi".getBytes(UTF_8); 99 final byte value1[] = "jkl".getBytes(UTF_8); 100 101 // Set a snapshot at start of transaction by setting setSnapshot(true) 102 try(final TransactionOptions txnOptions = new TransactionOptions() 103 .setSetSnapshot(true); 104 final Transaction txn = 105 txnDb.beginTransaction(writeOptions, txnOptions)) { 106 107 final Snapshot snapshot = txn.getSnapshot(); 108 109 // Write a key OUTSIDE of transaction 110 txnDb.put(writeOptions, key1, value1); 111 112 // Attempt to read a key using the snapshot. This will fail since 113 // the previous write outside this txn conflicts with this read. 114 readOptions.setSnapshot(snapshot); 115 116 try { 117 final byte[] value = txn.getForUpdate(readOptions, key1, true); 118 throw new IllegalStateException(); 119 } catch(final RocksDBException e) { 120 assert(e.getStatus().getCode() == Status.Code.Busy); 121 } 122 123 txn.rollback(); 124 } finally { 125 // Clear snapshot from read options since it is no longer valid 126 readOptions.setSnapshot(null); 127 } 128 } 129 130 /** 131 * Demonstrates "Read Committed" (Monotonic Atomic Views) isolation 132 * 133 * In this example, we set the snapshot multiple times. This is probably 134 * only necessary if you have very strict isolation requirements to 135 * implement. 136 */ readCommitted_monotonicAtomicViews( final TransactionDB txnDb, final WriteOptions writeOptions, final ReadOptions readOptions)137 private static void readCommitted_monotonicAtomicViews( 138 final TransactionDB txnDb, final WriteOptions writeOptions, 139 final ReadOptions readOptions) throws RocksDBException { 140 141 final byte keyX[] = "x".getBytes(UTF_8); 142 final byte valueX[] = "x".getBytes(UTF_8); 143 144 final byte keyY[] = "y".getBytes(UTF_8); 145 final byte valueY[] = "y".getBytes(UTF_8); 146 147 try (final TransactionOptions txnOptions = new TransactionOptions() 148 .setSetSnapshot(true); 149 final Transaction txn = 150 txnDb.beginTransaction(writeOptions, txnOptions)) { 151 152 // Do some reads and writes to key "x" 153 Snapshot snapshot = txnDb.getSnapshot(); 154 readOptions.setSnapshot(snapshot); 155 byte[] value = txn.get(readOptions, keyX); 156 txn.put(valueX, valueX); 157 158 // Do a write outside of the transaction to key "y" 159 txnDb.put(writeOptions, keyY, valueY); 160 161 // Set a new snapshot in the transaction 162 txn.setSnapshot(); 163 txn.setSavePoint(); 164 snapshot = txnDb.getSnapshot(); 165 readOptions.setSnapshot(snapshot); 166 167 // Do some reads and writes to key "y" 168 // Since the snapshot was advanced, the write done outside of the 169 // transaction does not conflict. 170 value = txn.getForUpdate(readOptions, keyY, true); 171 txn.put(keyY, valueY); 172 173 // Decide we want to revert the last write from this transaction. 174 txn.rollbackToSavePoint(); 175 176 // Commit. 177 txn.commit(); 178 } finally { 179 // Clear snapshot from read options since it is no longer valid 180 readOptions.setSnapshot(null); 181 } 182 } 183 } 184