Transaction Assist in Cloudera Operational Database (COD)


What’s CDP Operational Database (COD)

CDP Operational Database permits builders to shortly construct future-proof functions which are architected to deal with information evolution. It helps builders automate and simplify database administration with capabilities like auto-scale, and is absolutely built-in with Cloudera Knowledge Platform (CDP). For extra info and to get began with COD, confer with Getting Began with Cloudera Knowledge Platform Operational Database (COD).

Background

We’ve divided the “Transaction Assist in Cloudera Operational Database (COD)” weblog into two components.

  • On this first put up, we’re masking the overview and usages of transaction help in COD.
  • Within the second, we’re demonstrating the way to use transactions in your COD atmosphere with a step-by-step instance. See the way to use transactions in COD.

An outline of transaction help in COD

Transactions are a sequence of a number of adjustments in a database that should be accomplished in an order, or canceled to make sure integrity and consistency.

The transaction help in COD lets you carry out complicated distributed transactions and run atomic cross-row and cross-table database operations. The atomic database operations make sure that your database operations should both be accomplished or terminated.

COD helps Apache OMID (Optimistically Transaction Administration In Datastores) transactional framework that enables huge information functions to execute ACID transactionsadhering to the ACID properties of atomicity, consistency, isolation and sturdinesson COD tables. OMID offers lock-free transactional help on prime of HBase with snapshot isolation assure. OMID permits huge information functions to profit from the most effective of each worlds: the scalability supplied by NoSQL datastores resembling HBase, and the concurrency and atomicity supplied by transaction processing programs.

How COD manages transactions

When a number of transactions are occurring concurrently at totally different terminals, COD ensures both the HBase tables are up to date for every transaction finish to finish, marking the transaction as accomplished, or terminates the transaction and HBase tables aren’t up to date. COD archives this transaction administration utilizing OMID, which is a transactional processing service, together with HBase and Phoenix. 

COD additionally manages related configurations required to help transactions to be able to use transactions in functions with none further effort.

Figure1: OMID shopper view

COD routinely performs all of the steps to handle Phoenix transactions. These steps are described in Annexure1.

The way to use transactions with totally different functions

You should utilize COD transactions in streaming functions or OLTP (On-line Transaction Processing) functions in addition to batch-oriented Spark functions.

For extra particulars on deploying transaction help on COD, see The way to Use Transactions on COD

The next are the other ways and situations via which you should use COD transactions. 

1 (a): Phoenix thick shopper and skinny shopper (utilizing SQLLine command line) : 

// create transactional desk

0: jdbc:phoenix:> create desk bankaccount(customer_id varchar main key,title varchar, steadiness double) transactional=true;

No rows affected (2.287 seconds)

// Preliminary information inhabitants

0: jdbc:phoenix:> upsert into bankaccount values('CU001', 'foo', 100.0);

1 row affected (0.017 seconds)

0: jdbc:phoenix:> upsert into bankaccount values('CU002', ' baa', 100.0);

1 row affected (0.015 seconds)

0: jdbc:phoenix:> choose * from bankaccount;

+-------------+------+---------+

| CUSTOMER_ID | NAME | BALANCE |

+-------------+------+---------+

| CU001       | foo  | 100.0   |

| CU002       |  baa | 100.0   |

+-------------+------+---------+

// Auto commit off

0: jdbc:phoenix:> !autocommit off

Autocommit standing: false

// Begins transaction 1 to switch 50 from CU001 to CU002

0: jdbc:phoenix:> upsert into bankaccount(customer_id, steadiness) choose customer_id, steadiness - 50 from bankaccount the place customer_id = 'CU001';

1 row affected (0.075 seconds)

0: jdbc:phoenix:> upsert into bankaccount(customer_id, steadiness) choose customer_id, steadiness + 50 from bankaccount the place customer_id = 'CU002';

1 row affected (0.021 seconds)

0: jdbc:phoenix:> !commit

Commit full (0.044 seconds)

0: jdbc:phoenix:> choose * from bankaccount;

+-------------+------+---------+

| CUSTOMER_ID | NAME | BALANCE |

+-------------+------+---------+

| CU001       | foo  | 50.0    |

| CU002       |  baa | 150.0   |

+-------------+------+---------+

2 rows chosen (0.068 seconds)

// Begins transaction 2  to switch 20 from CU001 to CU002

0: jdbc:phoenix:> upsert into bankaccount(customer_id, steadiness) choose customer_id, steadiness - 20 from bankaccount the place customer_id = 'CU001';

1 row affected (0.014 seconds)

0: jdbc:phoenix:> upsert into bankaccount(customer_id, steadiness) choose customer_id, steadiness + 20 from bankaccount the place customer_id = 'CU002';

1 row affected (0.349 seconds)

// Rollback the adjustments

0: jdbc:phoenix:> !rollback 

Rollback full (0.007 seconds)

// Ought to get the identical outcome as above after rollback.

0: jdbc:phoenix:> choose * from bankaccount;

+-------------+------+---------+

| CUSTOMER_ID | NAME | BALANCE |

+-------------+------+---------+

| CU001       | foo  | 50.0    |

| CU002       |  baa | 150.0   |

+-------------+------+---------+

2 rows chosen (0.038 seconds)


1 (b): Phoenix thick and skinny shopper (utilizing Java utility):

attempt (Connection conn = DriverManager.getConnection(jdbcUrl)) {
 Assertion stmt = conn.createStatement();

 stmt.execute("CREATE TABLE IF NOT EXISTS ITEM " +

     " (id varchar not null main key, title varchar, amount integer) transactional=true");

 conn.setAutoCommit(false);

 stmt = conn.createStatement();

 stmt.execute("UPSERT INTO ITEM VALUES('ITM001','E-book', 5)");

 stmt.execute("UPSERT INTO ITEM VALUES('ITM002','Pen', 5)");

 conn.commit();

 stmt.execute("UPSERT INTO ITEM VALUES('ITM003','Cleaning soap', 5)");

 conn.rollback();

 ResultSet rs = stmt.executeQuery("SELECT rely(*) FROM ITEM");

 // The variety of rows needs to be two.

 System.out.println("Variety of rows " + rs.subsequent());

}

With exception dealing with

attempt (Connection conn = DriverManager.getConnection(jdbcUrl)) {

   attempt {

       Assertion stmt = conn.createStatement();

       stmt.execute("CREATE TABLE IF NOT EXISTS ITEM " +

               " (id varchar not null main key, title varchar, amount integer) transactional=true");

       conn.setAutoCommit(false);

       stmt = conn.createStatement();

       stmt.execute("UPSERT INTO ITEM VALUES('ITM001','E-book', 5)");

       stmt.execute("UPSERT INTO ITEM VALUES('ITM002','Pen', 5)");

       conn.commit();

   } catch (SQLException e) {

       LOG.error("Error occurred whereas performing transaction:", e);

       conn.rollback();

       // dealing with the exception object

       throw new RuntimeException(e);

   }

}

2: Phoenix spark utility: you should use Phoenix-Spark connector transactions to retry the Spark duties if there are any conflicts with different jobs or streaming functions.

COD helps the next two sorts of transactions whereas writing into the tables. 

  1. Batch clever transactions: Set phoenix.upsert.batch.measurement to any constructive integer worth to create transactions for a batch of a specific variety of rows.
  2. Partition clever transactions: Set phoenix.upsert.batch.measurement to 0 to create one transaction per job.

Git hyperlink for the instance code: https://github.com/cloudera/cod-examples/tree/fundamental/phoenix-spark-transactions

val tableName: String = "SPARK_TEST"

val conn = DriverManager.getConnection(url)

var stmt = conn.createStatement();

stmt.execute("CREATE TABLE SPARK_TEST

 " (ID INTEGER PRIMARY KEY, COL1 VARCHAR, COL2 INTEGER) TRANSACTIONAL=true" +

 " SPLIT ON (200, 400, 600, 800, 1000)")

val spark = SparkSession

 .builder()

 .appName("phoenix-test")

 .grasp("native")

 .getOrCreate()

val schema = StructType(

 Seq(StructField("ID", IntegerType, nullable = false),

   StructField("COL1", StringType),

   StructField("COL2", IntegerType)))

// Write rows from 1 to 500.

var dataSet = Checklist(Row(1, "1", 1), Row(2, "2", 2))

for (w <- 3 to 500) {

 dataSet = dataSet :+ Row(w, "foo", w);

}

var rowRDD = spark.sparkContext.parallelize(dataSet)

var df = spark.sqlContext.createDataFrame(rowRDD, schema)

// Batch clever transactions:

// ========================

// Setting batch measurement to 100. For every batch of 100 information one transaction will get created.

var extraOptions = "phoenix.transactions.enabled=true,phoenix.upsert.batch.measurement=100";

df.write

 .format("phoenix")

 .choices(Map("desk" -> tableName, PhoenixDataSource.ZOOKEEPER_URL -> zkUrl,

   PhoenixDataSource.PHOENIX_CONFIGS -> extraOptions))

 .mode(SaveMode.Overwrite)

 .save()

// Write rows from 500 to 1000.

dataSet = Checklist(Row(501, "500", 500), Row(502, "502", 502))

for (w <- 503 to 1000) {

 dataSet = dataSet :+ Row(w, ""+w, w);

}

// Partition clever transactions:

// ===========================

// Setting batch measurement 0 means for partition one transaction will get created.

rowRDD = spark.sparkContext.parallelize(dataSet)

df = spark.sqlContext.createDataFrame(rowRDD, schema)

extraOptions = "phoenix.transactions.enabled=true,phoenix.upsert.batch.measurement=0";

df.write

 .format("phoenix")

 .choices(Map("desk" -> tableName, PhoenixDataSource.ZOOKEEPER_URL -> zkUrl,

   PhoenixDataSource.PHOENIX_CONFIGS -> extraOptions))

 .mode(SaveMode.Overwrite)

 .save()


The way to use transactions with totally different instruments 

The principle operations that you just use whereas accessing COD transactions are auto commit on/off, commit, and rollback. These operations are carried out in numerous methods with totally different instruments.

On this part, yow will discover a hyperlink to a preferred SQL improvement instrument like DbVisualizer and an instance snippet.

DbVisualizer:

https://confluence.dbvis.com/show/UG100/Auto+Commitpercent2C+Commit+and+Rollback

Abstract

On this weblog put up, we’ve mentioned how COD manages transactions occurring at a number of terminals utilizing OMID. We’ve additionally included varied situations the place you embody COD transactions and an end-to-end circulate describing how one can implement transactions in an actual time state of affairs.

So, are you able to check out COD transactions help? Right here’s your first step on making a database utilizing COD.

Annexure

Annexure1:

Step 1: The next property in HBase UI > Configurations tab is ready as ‘true’.

phoenix.transactions.enabled=true


Step 2: COD generates OMID shopper configuration file, hbase-omid-client-config.yml, that accommodates the transaction server handle.

You should utilize the next command to obtain the shopper configuration file and use the configuration in utility classpath together with hbase-site.xml.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles