Mysql - Table lock error - mysql

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)

Related

Re: MySQL 8.0 Command Line Client Error 1205

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

is this a mysql bug about update check?

we have databases db1 and db2, each of them has a table t with a column a
create database db1;
create database db2;
create table t(a int);
insert into t values (1);
then we use db1 and run the SQLs:
mysql> update db2.t, (select 1 as a) as t set db2.t.a=1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0
mysql> update (select 1 as a) as t, db2.t set db2.t.a=1;
ERROR 1288 (HY000): The target table t of the UPDATE is not updatable
As you can see, the first SQL runs successfully, and the second report an error.
Why does this happen? is this a MySQL bug?
I am using MySQL version:
mysql> select version();
+-------------------------+
| version() |
+-------------------------+
| 8.0.22-0ubuntu0.20.04.3 |
+-------------------------+
1 row in set (0.00 sec)

READ COMMITTED ERROR 1665 impossible to write to binary log

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';

Rollback does not work in MySQL

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

Confused about the Mysql lock

I have a question about MySQL InnoDB. For example: I have thread A to start a transaction:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set name = "Jim" where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
And then, I just leave the thread A as it is. I started another thread B to do this:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set name = "Tom" where id = 1;
And I got the error:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
It makes sense, because thread A put a 'X' lock on that row.
And then I used thread B to do this:
mysql> start transaction;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from user where id = 1;
+----+------+
| id | name |
+----+------+
| 1 | wlq3 |
+----+------+
1 row in set (0.00 sec)
Here I'm confused. Like I just said thread A put a 'X' lock on that row. why thread B can read this row. In my opinion, reading data need a share lock, but exclusive lock is already on that data. Is there anyone can help me ,thanks!
By the way, the isolation level of thread A is repeatable read, and thread B is read committed.
Well wlq3 is the committed value in the database so transaction B reads this value. The update with Jim has not committed yet.A lock will not block a read it will just block a update this is due to the MVCC locking model which is implemented in InnoDB.
See this link for more information: InnoDB's row locking the same as MVCC Non-Blocking Reads?