How to detect transaction is running in Percona? - mysql

For example this is working for MariaDB and all three queries return 1:
START TRANSACTION;
SELECT ##in_transaction;
SELECT variable_value FROM information_schema.session_variables WHERE variable_name = 'in_transaction';
SELECT session_value FROM information_schema.system_variables WHERE variable_name = 'in_transaction';
And all these queries are not working for Percona 8.0.22-13.

MySQL 5.7 and 8.0 supports this (I haven't checked 5.6 because it's past end-of-life already), and therefore Percona should too, because Percona is a branch (not a fork) of MySQL.
mysql> select * from information_schema.innodb_trx
where trx_mysql_thread_id = connection_id()\G
If it returns no result, then the thread has not started a transaction.
Note that you can use start transaction and yet the query returns no result. A transaction does not really start until you execute the first statement against a transactional table.

Related

Is it possible to create a Lost Update with MySQL Workbench

I want to create a Lost Update with MySQL Workbench. Therefore, I have 2 connections to my database and 2 transactions. I also changed the transaction isolation level to read uncommitted but transaction A uses the current data when the update statement starts. It never uses the data from the first select statement and with select ... for update the transaction b is blocked.
Transaction A (starts first):
Start transaction;
SELECT * FROM table;
Select sleep(10); -- <- Transaction B executes in this 10 seconds
UPDATE table SET Number = Number + 10 WHERE FirstName = "Name1";
COMMIT;
Transaction B:
Start transaction;
UPDATE table SET Number = Number - 5 WHERE FirstName = "Name1";
COMMIT;
Is it possible to create this failure with MySQL Workbench. What´s wrong with my code?
Thanks for your help
The update in A work with data after the sleep is executed. Select before does nothing in the transaction.

mysql.gtid_executed table on 5.7.14 empty while ##global.gtid_executed is not

Starting MySQL 5.7.6, mysql.gtid_executed is supposed to keep track of all gtids executed.
However in MySQL 5.7.14, I am seeing a scenario as below
mysql> select ##global.gtid_executed;
+-----------------------------------------------------------------------+
| ##global.gtid_executed |
+-----------------------------------------------------------------------+
| cd5cd102-6586-0742-6f26-5b4c4c17d44d:4294967296:8589934592-8589939092 |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from mysql.gtid_executed;
Empty set (0.00 sec)
Can this discrepancy be explained?
As per the mysql documentation
If binary logging is enabled (log_bin is ON), whenever the binary log is rotated or the server is shut down, the server writes GTIDs for all transactions that were written into the previous binary log into the mysql.gtid_executed table. This situation applies on a replication source server, or a replica where binary logging is enabled.
I was seeing the same behavior when mysql starts up but after flushing the logs FLUSH LOGS; could see the GTID range in the mysql.gtid_executed table.

Mysql slow performance of very simple SELECT stored procedures

I am calling a stored procedure from JAVA, and it runs very slowly (about 120ms), even if it doesn't do much. For example:
BEGIN
SELECT '1';
END
If I have the stored procedure do literally nothing, or if I run the select commands outside of a stored procedure (ie execute the select * from.. directly in code), then it runs quickly (3ms or so).
BEGIN
END
I have 50 other SELECT stored procedures, and they all run equally slowly. If I run any if these commands outside of stored procedures (ie execute the SELECT * FROM... statement from JAVA without stored procedures), then they run very quickly.
I did look around and found others with similar issues, but couldn't find an answer that works in my case. I confirmed that collation and character set are the same between the database, the table, and the stored procedure.
INSERTS seem to run quickly. It really seems isolated to SELECT commands.
Environment: FreeBSD 10.3, DB - MariaDB 10.0.21
EDIT: Running the stored procedures from mysql commandline executes very quickly (0.00 sec).
EDIT: I enabled the general log and have the following output:
184381 Connect qwkdb#localhost as anonymous on productdb
184381 Query /* mysql-connector-java-6.0.2 ( Revision: c6da0fe501ad43d4ed6483b60ea796dc9fbe2d7b ) */SELECT ##session.auto_increment_increment AS auto_increment_increment, ##character_set_client AS character_set_client
, ##character_set_connection AS character_set_connection, ##character_set_results AS character_set_results, ##character_set_server AS character_set_server, ##init_connect AS init_connect, ##interactive_timeout AS interactive_timeout, ##l
icense AS license, ##lower_case_table_names AS lower_case_table_names, ##max_allowed_packet AS max_allowed_packet, ##net_buffer_length AS net_buffer_length, ##net_write_timeout AS net_write_timeout, ##query_cache_size AS query_cache_size
, ##query_cache_type AS query_cache_type, ##sql_mode AS sql_mode, ##system_time_zone AS system_time_zone, ##time_zone AS time_zone, ##tx_isolation AS tx_isolation, ##wait_timeout AS wait_timeout
184381 Query SET NAMES latin1
184381 Query SET character_set_results = NULL
184381 Query SET autocommit=1
184381 Query SET sql_mode = 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'
184381 Query SELECT name, type, comment FROM mysql.proc WHERE name like 'GetAttributeValue' and db <=> 'productdb' ORDER BY name, type
184381 Query SHOW CREATE PROCEDURE productdb.GetAttributeValue
184381 Query CALL GetAttributeValue('hi')

SQL update statement - Postgres and mysql compatibility

In mysql, one can execute the following statement:
UPDATE trx SET lock_id=somevalue WHERE lock_id is NULL order by stamp desc limit 1
I'm looking for a statement or statements run in transaction that would accomplish the same thing and would work in both MySQL 5.7 and PostgreSQL 9.4
It is important for this to be atomic, as this statement is in MySQL.

Show all current locks from get_lock

Is there any way to select / show all current locks that have been taken out using the GET_LOCK function?
Note that GET_LOCK locks are different from table locks, like those acquired with LOCK TABLES - readers who want to know how to see those locks should read Detecting locked tables (locked by LOCK TABLE)
From MySQL 5.7 onwards, this is possible, but requires first enabling the mdl instrument in the performance_schema.setup_instruments table. You can do this temporarily (until the server is next restarted) by running:
UPDATE performance_schema.setup_instruments
SET enabled = 'YES'
WHERE name = 'wait/lock/metadata/sql/mdl';
Or permanently, by adding the following incantation to the [mysqld] section of your my.cnf file (or whatever config files MySQL reads from on your installation):
[mysqld]
performance_schema_instrument = 'wait/lock/metadata/sql/mdl=ON'
(Naturally, MySQL will need to be restarted to make the config change take effect if you take the latter approach.)
Locks you take out after the mdl instrument has been enabled can be seen by running a SELECT against the performance_schema.metadata_locks table. As noted in the docs, GET_LOCK locks have an OBJECT_TYPE of 'USER LEVEL LOCK', so we can filter our query down to them with a WHERE clause:
mysql> SELECT GET_LOCK('foobarbaz', -1);
+---------------------------+
| GET_LOCK('foobarbaz', -1) |
+---------------------------+
| 1 |
+---------------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM performance_schema.metadata_locks
-> WHERE OBJECT_TYPE='USER LEVEL LOCK'
-> \G
*************************** 1. row ***************************
OBJECT_TYPE: USER LEVEL LOCK
OBJECT_SCHEMA: NULL
OBJECT_NAME: foobarbaz
OBJECT_INSTANCE_BEGIN: 139872119610944
LOCK_TYPE: EXCLUSIVE
LOCK_DURATION: EXPLICIT
LOCK_STATUS: GRANTED
SOURCE: item_func.cc:5482
OWNER_THREAD_ID: 35
OWNER_EVENT_ID: 3
1 row in set (0.00 sec)
mysql>
The meanings of the columns in this result are mostly adequately documented at https://dev.mysql.com/doc/refman/en/metadata-locks-table.html, but one point of confusion is worth noting: the OWNER_THREAD_ID column does not contain the connection ID (like would be shown in the PROCESSLIST or returned by CONNECTION_ID()) of the thread that holds the lock. Confusingly, the term "thread ID" is sometimes used as a synonym of "connection ID" in the MySQL documentation, but this is not one of those times. If you want to determine the connection ID of the connection that holds a lock (for instance, in order to kill that connection with KILL), you'll need to look up the PROCESSLIST_ID that corresponds to the THREAD_ID in the performance_schema.threads table. For instance, to kill the connection that was holding my lock above...
mysql> SELECT OWNER_THREAD_ID FROM performance_schema.metadata_locks
-> WHERE OBJECT_TYPE='USER LEVEL LOCK'
-> AND OBJECT_NAME='foobarbaz';
+-----------------+
| OWNER_THREAD_ID |
+-----------------+
| 35 |
+-----------------+
1 row in set (0.00 sec)
mysql> SELECT PROCESSLIST_ID FROM performance_schema.threads
-> WHERE THREAD_ID=35;
+----------------+
| PROCESSLIST_ID |
+----------------+
| 10 |
+----------------+
1 row in set (0.00 sec)
mysql> KILL 10;
Query OK, 0 rows affected (0.00 sec)
Starting with MySQL 5.7, the performance schema exposes all metadata locks, including locks related to the GET_LOCK() function.
See http://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html
SHOW FULL PROCESSLIST;
You will see the locks in there
If you just want to determine whether a particular named lock is currently held, you can use IS_USED_LOCK:
SELECT IS_USED_LOCK('foobar');
If some connection holds the lock, that connection's ID will be returned; otherwise, the result is NULL.
Reference taken from this post:
You can also use this script to find lock in MySQL.
SELECT
pl.id
,pl.user
,pl.state
,it.trx_id
,it.trx_mysql_thread_id
,it.trx_query AS query
,it.trx_id AS blocking_trx_id
,it.trx_mysql_thread_id AS blocking_thread
,it.trx_query AS blocking_query
FROM information_schema.processlist AS pl
INNER JOIN information_schema.innodb_trx AS it
ON pl.id = it.trx_mysql_thread_id
INNER JOIN information_schema.innodb_lock_waits AS ilw
ON it.trx_id = ilw.requesting_trx_id
AND it.trx_id = ilw.blocking_trx_id
I found following way which can be used if you KNOW name of lock
select IS_USED_LOCK('lockname');
however i not found any info about how to list all names.
Another easy way is to use:
mysqladmin debug
This dumps a lot of information (including locks) to the error log.