Is there a way in the JDBC connection string to specify ML workloads to connect to Spanner's Read-Only replicas? Spanner's infrastructure efficiently handles such Read-only transactions?
You cannot use the JDBC driver to connect directly to a read-only replica, but you can use read-only transactions and specify the read staleness of the transaction (or a single query). This will effectively allow Cloud Spanner to execute the query on the closest read-only replica. Use the SET READ_ONLY_STALENESS command for this.
Example for a single query:
-- Set the max staleness to 15 seconds.
-- Cloud Spanner will choose the most efficient timestamp to
-- execute the query. This only works in auto commit mode.
SET READ_ONLY_STALENESS='MAX_STALENESS 15s';
SELECT * FROM my_table;
Example for a read-only transaction with multiple queries:
BEGIN;
-- Mark the transaction as read-only.
SET TRANSACTION READ ONLY;
-- MAX_STALENESS can only be used in auto commit.
-- Use EXACT_STALENESS or READ_TIMESTAMP for transactions.
SET READ_ONLY_STALENESS='EXACT_STALENESS 15s';
SELECT * FROM my_table;
SELECT * FROM other_table;
-- Read-only transactions are not really committed, but this
-- marks the end of the transaction for the JDBC driver.
COMMIT;
Related
Does anyone know the reason, yugabyte-specific or otherwise, that I cannot alternate between truncating and inserting within the same transaction?
These steps:
Truncate a table.
Insert a row into that table.
Truncate again.
Insert another row into the table.
Result in this error on the final step:
ERROR: Operation failed. Try again.: Unknown transaction, could be recently aborted: e415ae05-0d46-42f5-b18d-f27b344b5642 (SQLSTATE 40001)
[Disclaimer]: This question was first asked on the YugabyteDB Community Slack channel.
In YugabyteDB, currently 'truncate' is not transactional. The recommendation would be to avoid using:
a) truncate inside of a multi-step transaction
OR
b) running truncate concurrently with our read/write operations on the same table.
To my knowledge other distributed SQL databases also either:
a) do not support truncate (like Google Cloud Spanner). See Does Cloud Spanner support a TRUNCATE TABLE command?
OR,
b) they support truncate, but not in transactional manner.
We do plan to restrict this restriction in future. In the near term perhaps
delete from T;
can be used as a workaround; this is a bit heavier weight than using truncate, but will be transactional.
We have two CAS queries. It was working just fine with 2 containers per region. We have increased containers from 2 to 3 then we started seeing the WriteTimeoutException. The traffic is same or even less compared to the regular business hours. Cassandra is in 3 regions and each cluster has 3 hosts.
Not sure what could be the reason for these errors, but the change was increase in the application container by one. Appreciate if any help here to debug further.
UPDATE order_sequences USING TTL 10 set instance_name = ? where id_name = ? IF instance_name = null", ConsistencyLevel.QUORUM)
UPDATE order_sequences SET next_id= ? where id_name= ? IF next_id= ? AND instance_name = ?", ConsistencyLevel.QUORUM),
Error stack:
com.datastax.driver.core.exceptions.WriteTimeoutException: Cassandra timeout during CAS write query at consistency SERIAL (7 replica were required but only 0 acknowledged the write) at
com.datastax.driver.core.exceptions.WriteTimeoutException.copy(WriteTimeoutException.java:85) at
com.datastax.driver.core.exceptions.WriteTimeoutException.copy(WriteTimeoutException.java:23) at
com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:35) at
com.datastax.driver.core.ChainedResultSetFuture.getUninterruptibly(ChainedResultSetFuture.java:59) at
com.datastax.driver.core.NewRelicChainedResultSetFuture.getUninterruptibly(NewRelicChainedResultSetFuture.java:11) at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:58) at
CAS write are a specialized metric which are triggered when a compare and set is conducted. LWT transaction is known as compare and set (CAS); replica data is compared and any data found to be out of date is set to the most consistent value.
In Cassandra, the process combines the Paxos protocol with normal read and write operations to accomplish the compare and set operation.
The Paxos protocol is implemented as a series of phases:
• Prepare/Promise
• Read/Results
• Propose/Accept
• Commit/Acknowledge
These four phases require four round trips between a node proposing a lightweight transaction and any cluster replicas involved in the transaction. The performance will be affected. Consequently, reserve lightweight transactions for situations where concurrency must be considered.
For example, the following series of operations can fail:
DELETE ...
INSERT .... IF NOT EXISTS
SELECT ....
The following series of operations will work:
DELETE ... IF EXISTS
INSERT .... IF NOT EXISTS
SELECT .....
Would strongly recommend you to check the "CAS write latency" statistics from
"nodetool proxyhistograms" command, it provides a histogram of network statistics at the time of the command.
Could you please let me know in case if you are still facing this error ?
I'm current using DB2 and planning to use cassandra because as i know cassandra have a read performance greater than RDBMS.
May be this is a stupid question but I have experiment that compare read performance between DB2 and Cassandra.
Testing with 5 million records and same table schema.
With query SELECT * FROM customer. DB2 using 25-30s and Cassandra using 40-50s.
But query with where condition SELECT * FROM customer WHERE cusId IN (100,200,300,400,500) DB2 using 2-3s and Cassandra using 3-5ms.
Why Cassandra faster than DB2 with where condition? So i can't prove which database is greater with SELECT * FROM customer right?
FYI.
Cassandra: RF=3 and CL=1 with 3 nodes each node run on 3 computers (VM-Ubuntu)
DB2: Run on windows
Table schema:
cusId int PRIMARY KEY, cusName varchar
If you look at the types of problems that Cassandra is good at solving, then the reasons behind why unbound ("Select All") queries suck become quite apparent.
Cassandra was designed to be a distributed data base. In many Cassandra storage patterns, the number of nodes is greater than the replication factor (I.E., not all nodes contain all of the data). Therefore, limiting the number of network hops becomes essential to modeling high-performing queries. Cassandra performs very well with specific queries (which utilize the partition/clustering key structure), because it can quickly locate the node primarily responsible for the data.
Unbound queries (A.K.A. multi-key queries) incur the extra network time because a coordinator node is required. So one node acts as the coordinator, queries all other nodes, collates data, and returns the result set. Specifying a WHERE clause (with at least a partition key) and while using a "Token Aware" load balancing policy, performs well for two reasons:
A coordinator node is not required.
The node primarily responsible for the range is queried, returning the result set in a single netowrk hop.
tl;dr;
Querying Cassandra with an unbound query, causes it to incur a lot of extra processing and network time that it normally wouldn't have to do, had the query been specified with a WHERE clause.
Even as a troublesome query like a no-condition range query, 40-50s is pretty extreme for C*. Is the coordinator hitting GCs with the coordination? Can you include code used for your test?
When you make a select * vs millions of records, it wont fetch them all at once, it will grab the fetchSize at a time. If your just iterating through this, the iterator will actually block even if you used executeAsync initially. This means that every 10k (default) records it will issue a new query that you will block on. The serialized nature of this will take time just from a network perspective. http://docs.datastax.com/en/developer/java-driver/3.1/manual/async/#async-paging explains how to do it in a non-blocking way. You can use this to to kick off the next page fetch while processing the current which would help.
Decreasing the limit or fetch size could also help, since the coordinator may walk token ranges (parallelism is possible here but its heuristic is not perfect) one at a time until it has read enough. If it has to walk too many nodes to respond it will be slow, this is why empty tables can be very slow to do a select * on, it may serially walk every replica set. With 256 vnodes this can be very bad.
I have one node with replication factor 1 and fire a batch statement query on that node ,cassandra writes the data but failed to acknowledge with in timeout limit . then it gives a write timout exception with following stacktrace .
failed `Exception in thread "main" com.datastax.driver.core.exceptions.WriteTimeoutException: Cassandra timeout during write query at consistency ONE (1 replica were required but only 0 acknowledged the write)
at com.datastax.driver.core.exceptions.WriteTimeoutException.copy(WriteTimeoutException.java:54)
at com.datastax.driver.core.ResultSetFuture.extractCauseFromExecutionException(ResultSetFuture.java:271)
at com.datastax.driver.core.ResultSetFuture.getUninterruptibly(ResultSetFuture.java:187)
at com.datastax.driver.core.Session.execute(Session.java:126)
at jason.Stats.analyseLogMessages(Stats.java:91)
at jason.Stats.main(Stats.java:48)
then if you go back and check the table then you will find data has been written . So my question is , if cassandra gives write timout exception then it should rollback the changes .
I mean i don't want to write to database if i am getting write timout exception ,is there any rollback strategy present for that particular scenario .
Based on your description what you are expecting is that Cassandra supports ACID compliant transaction at least with regards to the A - Atomicity. Cassandra does not provide ACID-compliant transactions instead it relies on eventual consistency to provide a durable data store. Cassandra does provide Atomicity in as much as a single partition on a node is atomic by which I mean an entire row will either be written or not. However a write can still succeed on one or more replicas but after the timeout set by your client. In this case the client would receive an error but the data would be written. There is nothing that will rollback that transaction. Instead the data in the cluster will become consistent using the normal repair mechanisms.
My suggestion for you would be to:
In the case of a timeout do a retry of the write query
Investigate why you are getting a timeout error on a write with a CL=ONE. If this is a multi-DC sort of setup have you tried CL=LOCAL_ONE.
Some docs to read:
https://docs.datastax.com/en/cassandra/2.1/cassandra/dml/dml_atomicity_c.html
https://docs.datastax.com/en/cassandra/2.1/cassandra/operations/opsRepairNodesReadRepair.html
Cassandra does not have any notion of rollbacks. If a write times out that means that the write may have succeeded or may not have. This is why C* tries to focus users on idempotent data models and structures.
The only means of actually performing some kind of conditional write is via Light Weight Transactions which allow for some check and set operations.
In the earlier beta releases of CQL, there was a command I could use to set the read / write consistency of an individual CQL operation. It looked like this:
SELECT * FROM users WHERE state='TX' USING CONSISTENCY QUORUM;
I use CQL3 regularly and have a use-case where I need to be able to perform a read with a higher consistency level than the rest of our application.
I looked through the CQL3 reference and didn't find any mention of any CQL syntax that allows me to change the consistency settings on a per-query basis, unless I'm using cqlsh (not useful for application development.)
How am I supposed to tune the consistency on a per-request basis using CQL3?
First set the consistency by running command:
CONSISTENCY QUORUM;
and then then run you query:
SELECT * FROM users WHERE state='TX'
At any point you can check the consistency using:
CONSISTENCY;
Aaron, the Consistency Level is not needed to be set on the protocol level - for the reasons explained here: https://issues.apache.org/jira/browse/CASSANDRA-4734
The default consistency level for any query is "ONE". However, one can set the consistency level on query basis as below.
Based on the Replication factor, the location of the partition (nodes list) can be found as below.
nodetool getendpoints Keyspace-name table-name partition-key value
$ nodetool getendpoints stresstest status bill
10.134.38.15
10.134.38.24
10.134.38.26