I'm using InnoDb engine by default. And this is what looks strange:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> create table test_1(id int);
Query OK, 0 rows affected (0.07 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> show tables;
+------------------+
| Tables_in_reestr |
+------------------+
| test_1 |
+------------------+
1 rows in set (0.00 sec)
It looks strange, because I started transaction and rollbacked, but to no avail. So, what I'm doing wrong?
To expand on the comment above: in MySQL, basically all operations that alter database objects perform auto-commit. The main categories are:
any DDL on your objects, like CREATE/ALTER/DROP TABLE/VIEW/INDEX...,
anything that modifies the system database mysql, like ALTER/CREATE USER,
any administrative commands, like ANALYZE,
any data loading/replication statements.
Actually, I find it best to assume that INSERT, UPDATE and DELETE are safe, and anything else is not.
Source: https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
Related
MySQL 8.0 Command Line Client is giving me a timeout error and I have restarting the transaction by typing "start transaction" another time. Keep in mind that I have another command line open with the table CIA_DATA.new_table and it is also being updated with the same changes. (I am doing this to follow a tutorial.) Here is the script:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update CIA_DATA.new_table set c1 = 2 where c1 = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Updated code for help in Answers Comments:
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> drop table CIA_DATA.new_table;
ERROR 1051 (42S02): Unknown table 'cia_data.new_table'
mysql> create table CIA_DATA.new_table ( c1 int primary key);
Query OK, 0 rows affected (0.08 sec)
mysql> insert into CIA_DATA.new_table values (1);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.05 sec)
mysql> select * from CIA_DATA.new_table;
+----+
| c1 |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
mysql> update CIA_DATA.new_table set c1 = 2 where c1 = 1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> close transaction
-> \c
mysql> close transaction;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'close transaction' at line 1
mysql> --innodb-lock-wait-timeout=#
-> \c
mysql> --innodb-lock-wait-timeout=#;
->
Thanks,
thecoolgeek
What happen ony your computer:
One transaction locks the table and you didn't release the lock by endind the transaction.
you start a new tansaction and it encounters a lockesd table and waits for the release
As the first transaction and the lock wasn't released, the secnd goes into to timeout.
Locks are in the best case difficult. and sometimes it takes hours or days to solve them.
so close the tranaction as fast as you can, so that the timeout not happen or increase the timeout https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout
THis example works :
MariaDB [test]> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> INSERT INTO test(id, value) VALUES (1, 'test'), (2, 'test 2');
Query OK, 2 rows affected (0.37 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [test]> SELECT * FROM test;
+------+--------+
| id | value |
+------+--------+
| 1 | test |
| 2 | test 2 |
+------+--------+
2 rows in set (0.00 sec)
MariaDB [test]> COMMIT;
but when i changed transaction level :
MariaDB [test]> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> INSERT INTO test(id, value) VALUES (1, 'test'), (2, 'test 2');
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log
since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine lim
ited to row-based logging. InnoDB is limited to row-logging when transaction iso
lation level is READ COMMITTED or READ UNCOMMITTED.
MariaDB [test]> SELECT * FROM test;
Empty set (0.00 sec)
MariaDB [test]> COMMIT;
Query OK, 0 rows affected (0.00 sec)
How to fix this problem ?
The error message is quite detailed in this case. According to mysql documentation on binlog_format:
If you are using InnoDB tables and the transaction isolation level is READ COMMITTED or READ UNCOMMITTED, only row-based logging can be used. It is possible to change the logging format to STATEMENT, but doing so at runtime leads very rapidly to errors because InnoDB can no longer perform inserts.
So, you have to set the binlog_format to ROW:
SET SESSION binlog_format = 'ROW';
I am experiencing some problems with table locking. I have locked certain number of table in transaction. LOCK TABLES t1 READ, t2 READ, t3 READ, t4 READ,t5 READ,t6 READ,t7 READ;
While reading its ok, but when I am trying to write/update to this tables it's showing the error Table 't1' was locked with a READ lock and can't be updated
But I never locked the table for write, I have to write to these tables with updated values.
My aim is I need to select and I need to update rows, while others should not interact with above tables until the process finished.
Much appreciated your solutions!
From mysql doc:
Rules for Lock Acquisition
To acquire table locks within the current session, use the LOCK TABLES statement. The following lock types are available:
READ [LOCAL] lock:
The session that holds the lock can read the table (but not write it).
MariaDB [test]> lock table super1 read;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select * from super1;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 5 |
| 6 |
| 7 |
+----+
6 rows in set (0.00 sec)
MariaDB [test]> insert into super1 VALUE(10);
ERROR 1099 (HY000): Table 'super1' was locked with a READ lock and can't be updted
other session can SELECT too
MariaDB [test]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> lock table super1 write;
Query OK, 0 rows affected (0.00 sec)
other session can't SELECT
MariaDB [test]> insert into super1 VALUE(10);
Query OK, 1 row affected (0.00 sec)
MariaDB [test]> insert into super1 VALUE(11);
Query OK, 1 row affected (0.00 sec)
MariaDB [test]> unlock tables;
Query OK, 0 rows affected (0.00 sec)
In the following MySQL code, the first two blocks drop and create a temporary table _temp (with different column labels) and select * from it without a problem. Then, I create a stored procedure that does the same thing (i.e., select * from _temp), and it works first time, but not the second, failing with
ERROR 1054 (42S22): Unknown column 'test._temp.f' in 'field list'
It seems like select * from _temp on its own correctly handles the change in table columns, but the previous columns names are remembered across stored procedure calls. Am I doing something wrong, or is there a workaround?
MySQL Code
drop temporary table if exists _temp;
create temporary table _temp select 'first' as f;
select * from _temp;
drop temporary table if exists _temp;
create temporary table _temp select 'second' as s;
select * from _temp;
drop procedure if exists selectTemp;
create procedure selectTemp()
select * from _temp;
drop temporary table if exists _temp;
create temporary table _temp select 'first' as f;
call selectTemp();
drop temporary table if exists _temp;
create temporary table _temp select 'second' as s;
call selectTemp();
Transcript
$ mysql --version
mysql Ver 14.14 Distrib 5.5.38, for debian-linux-gnu (x86_64) using readline 6.2
mysql> source temp.sql
Query OK, 0 rows affected (0.01 sec)
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
+-------+
| f |
+-------+
| first |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
+--------+
| s |
+--------+
| second |
+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
+-------+
| f |
+-------+
| first |
+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
ERROR 1054 (42S22): Unknown column 'test._temp.f' in 'field list'
After paring this down to a minimal working example, and distilling the essential elements, searching for a bug report, this became much easier. It turns out that this was reported all the way back in 2005 as:
Bug #12257 SELECT * inside PROCEDURE gives "Unknown column" on second loop if tbl changed
Some of the bugs marked as a duplicate of that are actually more along the lines of the example:
Bug #15766 select * from table inside stored procedure uses old field names
Bug #49333 Unknown column 'test.TEMPTABLE.column1' in 'field list'
Bug #62406 new cursor, on table with same name but different structure as used before fails
The bug is closed, but apparently not fixed yet, though 5.6 mentions the behavior. From the comments in the bug report:
Noted in 5.6.6 changelog.
"Unknown column" errors or bad data could result from changing the set
of columns in a table used within a stored program between executions
of the program or while the table was used within a program loop.
(MySQL 5.5, InnoDB tables) Why can't I rollback, either to a savepoint or to the previous begin statement?
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> savepoint id;
Query OK, 0 rows affected (0.00 sec)
mysql> alter table sg_Section add column (published tinyint(1) default 0);
Query OK, 2 rows affected (0.30 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> rollback to savepoint id;
ERROR 1305 (42000): SAVEPOINT id does not exist
When not running any command after the savepoint, it seems to «work»:
mysql> savepoint id;
Query OK, 0 rows affected (0.00 sec)
mysql> rollback to savepoint id;
Query OK, 0 rows affected (0.00 sec)
DDL is not transactional in MySQL.
Any DDL statement implicitly commits the open transaction.
More details in the manual: http://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html