how mysql proxy distinguish normal select or transaction select - mysql

https://dev.mysql.com/doc/refman/5.6/en/innodb-autocommit-commit-rollback.html
In InnoDB, all user activity occurs inside a transaction. If autocommit mode is enabled, each SQL statement forms a single transaction on its own.
each SQL is single transaction, how mysql proxy judge a select that should route to master or replica.

Related

FOR UPDATE lock is not released when database connection is disrupted [duplicate]

I need to make MySQL server to rollback transaction immediately after its client disconnected, because each client works concurrently. The problem can be reproduced like these (using an innodb table type)
On Client A:
START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... then disconnect your connection to the server
On Client B:
START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... lock wait time out will occur here
I had set MySQL's server option like innodb_rollback_on_timeout and using mysql's client mysql --skip-reconnect on both client. I tried this using one server and two client, on a network. I disconnected the network physically (unplug the cable) after SELECT ... FOR UPDATE; line. I need to make other clients to be able to use tblone on a transaction (lock it, update it) immediately, and for that to happen I think the server should rollback the transaction for Client A, after Client A disconnects.
When you are physically disconnecting a client you're not sending a normal disconnect (which would have caused a rollback) and the MySQL protocol isn't very chatty so the server never knows that the client isn't there. I think this is a flaw in the protocol when comparing to other database systems where the client and server talks internally much more.
Anyway. There are two variables that you could change. They basically do the same but for different clients.
The first is wait_timeout and it is used by application clients like java or php.
The other is interactive_timeout and it is used by the mysql client (as in your tests)
In both cases the server to kills the connection after a number of seconds and when doing so rollbacks all transactions and releases all locks.
This is to discuss some of the Comments. Please note that this disagrees with some of the Comments. I'll use an INSERT instead of SELECT..FOR UPDATE because the effect is more visible.
Let's look at some different cases:
(1) No SQL + timeout
START TRANSACTION;
do some SQL statement(s)
do no SQL for more than the timeout (before COMMITing)
Avoid this because of the cases detailed below. Solution: Don't depend on InnoDB to help you with long transactions.
(2) long-running query
START TRANSACTION;
do some SQL statement(s)
run an SQL query that takes more than the timeout
COMMIT;
All is well. The timeout does not apply as long as the server (mysqld) is continuing to perform queries. That is, the timeout 'clock' starts over at the end of each SQL statement
(3) (auto-reconnect)
START TRANSACTION;
INSERT ... VALUES (123);
time passes; no SQL performed for longer than the timeout
disconnect occurs
INSERT ... VALUES (456);
auto-reconnect (because you have it ENabled);
the INSERT proceeds
COMMIT;
123 will be rolled back; 456 will be inserted. (Similarly SELECT..FOR UPDATE would lose the locks.) Not good. The solution is to turn off "auto-reconnect". Instead, check for errors and treat the disconnect error as a fatal error for the Transaction. (Then start over the transaction.)
The INSERT 456 will be running in a new transaction, controlled by autocommit.
(4) (NO auto-reconnect)
START TRANSACTION;
INSERT ... VALUES (123);
time passes; no SQL for longer than the timeout
disconnect occurs
INSERT ... VALUES (456);
NO auto-reconnect (because you have it DISabled)
COMMIT;
123 will be rolled back. The INSERT of 456 will get an error something like "connection lost". Start the transaction over.

MySQL concurrent updates

I have small POS system with server side uses PHP and MySql (InnoDB).
When "Sale" is being completed the following query is executed for update stock quantity:
"UPDATE products SET qty=qty-:qty, ustatus=1 WHERE pid=:pid";
Does this statement is "Concurrency Update Secure", meaning do i need any transactions or locking tables.
I just want to be sure, that multiple queries like this, executed in same time
does not make mess with my stock.
If you use innodb, then all sql statements are executed in a transaction, you do not need to explicitly specify that.
Concurrency control is done via locks, not transactions. Transactions may only determine the lifespan of locks.
The update statement places an exclusive lock on the records that it wants to modify, meaning no other statements can modify (sometimes cannot even read) the locked record until the exclusive lock is released. So, your statement is safe from concurrency point of view.

How to stop SQLAlchemy session transaction in a query?

The SQLAlchemy's docs say: "When you use a session to query, the session get transaction started". In fact, every operation is a transaction.
But it has a question, I'm using a MySQL middleware--mycat for Read/Write Splitting, if you send a transaction, all queries are transferred to the write server, even if it is a select query.
I wish to let the query not enable transactions without using the raw SQL query. So how to stop SQLAlchemy session transaction? Or change MySQL middleware to better?

How mysql handle delete and select query at the same time?

I have some confusion regarding mysql handler to handle delete and select query at the same time. I need to know if delete query is running on a table and at the same time select is also running for that table and even for the same row.
MySql uses internal locking mechanism for this. Please check the following link also check for locking mechanisms in MySql.
http://dev.mysql.com/doc/refman/5.6/en/internal-locking.html
if the delete statement wasn't a part of transaction then the engine ,most mysql engines, will lock the related rows until the delete statement executed.
if the delete statement was a part of on going transaction then the ability to access that records are determined with the transaction isolation level.
The transaction isolation level determine whether other sessions can access the data that was affected by the transaction's statement ( in your case delete ) before the transaction is committed
if the isolation level is read committed and the transaction was not committed yet then any select statement outside the transaction block will retrieve the old data and after the transaction is committed the select will retrieve the new data.
for more details about isolation levels you can check this
http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html

MySQL rollback on transaction with lost/disconnected connection

I need to make MySQL server to rollback transaction immediately after its client disconnected, because each client works concurrently. The problem can be reproduced like these (using an innodb table type)
On Client A:
START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... then disconnect your connection to the server
On Client B:
START TRANSACTION;
SELECT MAX(ID) FROM tblone FOR UPDATE;
#... lock wait time out will occur here
I had set MySQL's server option like innodb_rollback_on_timeout and using mysql's client mysql --skip-reconnect on both client. I tried this using one server and two client, on a network. I disconnected the network physically (unplug the cable) after SELECT ... FOR UPDATE; line. I need to make other clients to be able to use tblone on a transaction (lock it, update it) immediately, and for that to happen I think the server should rollback the transaction for Client A, after Client A disconnects.
When you are physically disconnecting a client you're not sending a normal disconnect (which would have caused a rollback) and the MySQL protocol isn't very chatty so the server never knows that the client isn't there. I think this is a flaw in the protocol when comparing to other database systems where the client and server talks internally much more.
Anyway. There are two variables that you could change. They basically do the same but for different clients.
The first is wait_timeout and it is used by application clients like java or php.
The other is interactive_timeout and it is used by the mysql client (as in your tests)
In both cases the server to kills the connection after a number of seconds and when doing so rollbacks all transactions and releases all locks.
This is to discuss some of the Comments. Please note that this disagrees with some of the Comments. I'll use an INSERT instead of SELECT..FOR UPDATE because the effect is more visible.
Let's look at some different cases:
(1) No SQL + timeout
START TRANSACTION;
do some SQL statement(s)
do no SQL for more than the timeout (before COMMITing)
Avoid this because of the cases detailed below. Solution: Don't depend on InnoDB to help you with long transactions.
(2) long-running query
START TRANSACTION;
do some SQL statement(s)
run an SQL query that takes more than the timeout
COMMIT;
All is well. The timeout does not apply as long as the server (mysqld) is continuing to perform queries. That is, the timeout 'clock' starts over at the end of each SQL statement
(3) (auto-reconnect)
START TRANSACTION;
INSERT ... VALUES (123);
time passes; no SQL performed for longer than the timeout
disconnect occurs
INSERT ... VALUES (456);
auto-reconnect (because you have it ENabled);
the INSERT proceeds
COMMIT;
123 will be rolled back; 456 will be inserted. (Similarly SELECT..FOR UPDATE would lose the locks.) Not good. The solution is to turn off "auto-reconnect". Instead, check for errors and treat the disconnect error as a fatal error for the Transaction. (Then start over the transaction.)
The INSERT 456 will be running in a new transaction, controlled by autocommit.
(4) (NO auto-reconnect)
START TRANSACTION;
INSERT ... VALUES (123);
time passes; no SQL for longer than the timeout
disconnect occurs
INSERT ... VALUES (456);
NO auto-reconnect (because you have it DISabled)
COMMIT;
123 will be rolled back. The INSERT of 456 will get an error something like "connection lost". Start the transaction over.