Can I call update/insert into table(tb1) after calling: LOCK TABLES tb1 READ?
I've read the MySQL manual which says about read lock:
The session that holds the lock can read the table (but not write it).
I'm looking for a lock which allows me to READ/WRITE a table but allowing others only READ access.
How to do it?
Mine is MyISAM database.
You can't do it in MySQL. The best way is to use WRITE lock but then all other sessions will have to wait for ability to read from table.
You probably want to read these first :
http://dev.mysql.com/doc/refman/5.0/en/locking-issues.html
http://en.wikipedia.org/wiki/Isolation_(database_systems)
Read also about lock escalations.
I had issues with earlier versions(4.x) of mysql where I couldn't update the same
table where I was reading from.
Related
Why mysql add a read lock to myisam engine table when select data?
On the official manual,it only mention that innodb has a default isolation.And we know the myisam engine does not support transaction.But why the mysql add a read lock to the selecting table?
If a table were modified while a query was reading from it, the read query might return incorrect results. To prevent this, MyISAM uses a lock* to prevent writes from being made to a table while any other threads are reading from that table. This lock doesn't prevent other read queries, though - any number of threads can share the lock.
Tables are also locked while a query is writing to them. This uses a different type of lock to prevent any other writes or reads from taking place on that table.
I need to perform some scripted actions, which may take a while (like maybe a minute). At the beginning of these actions, I take some measures from the MySQL DB and it's important that they do not change until the actions are done. The DB has dozens of tables since it belongs to a quite old fashioned but huge CMS, and the CMS users have a dozen options to modify it.
I do not even want to change anything in the time my scripts runs in the DB myself, it just shall be frozen. It's not a Dump or Update. But tables should be kept open for reading for everyone, to prevent visitors of the connected homepage from getting errors.
If the database altering actions, which may be performed by other CMS users in the meantime would be triggered after the DB is unlocked again, it would be perfect, but if they fail, I would not mind.
So I thought at the beginning of the script I lock the tables down with
lock first_table write;
lock second_table write;
...
And after I do
unlock tables
I think that should do exactly what I want. But can I archive this for all tables of the db without naming them explicitly, to make this more futureproof?
This does not work for sure:
lock tables (select TABLE_NAME from information_schema.tables
where table_schema='whatever') write;
Another question would be, if someone can answer this on the fly, if I would have to perfom the lock/unlock with another MYSQL user than the one used by the CMS. If I understood this right, then yes.
Below is the statement to lock all tables (actually it creates a single global lock):
FLUSH TABLES WITH READ LOCK;
Then release it with:
UNLOCK TABLES;
Mysqldump does this, for example, unless you are backing up only transactional tables and use the --single-transaction option.
Read http://dev.mysql.com/doc/refman/5.7/en/flush.html for more details about FLUSH TABLES.
Re your comment:
Yes, this takes a global READ LOCK on all tables. Even your own session cannot write. My apologies for overlooking this requirement of yours.
There is no equivalent global statement to give you a write lock. You'll have to lock tables by name explicitly.
There's no syntax for wildcard table names, nor is there syntax for putting a subquery in the LOCK TABLES statement.
You'll have to get a list of table names and build a dynamic SQL query.
I am using code like
$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->query('AND YET ANOTHER QUERY...');
$this->db->trans_complete();
same table is used for other read purpose. I don't want other user to read the records until i have finished writing all records. Will transactions take care of it?
If the storage engine from the table support transactions it does.
If you have MyISAM (or mixed) tables you can use LOCK TABLES instead.
LOCK TABLES
table1 WRITE,
table2 WRITE
You'll have to lock all the tables you want to query within the 'transaction'
After you're done use UNLOCK TABLES
Is it possible to lock a single table on MySQL for a session and still be able to read and write on other unlocked tables on the same session that locked that table while the table is still locked?
Yes, LOCK TABLES does exactly this.
So after reading Performance in PDO / PHP / MySQL: transaction versus direct execution in regards to performance issues I was thinking about I did some research on locking tables in MySQL.
On http://dev.mysql.com/doc/refman/5.0/en/table-locking.html
Table locking enables many sessions to
read from a table at the same time,
but if a session wants to write to a
table, it must first get exclusive
access. During the update, all other
sessions that want to access this
particular table must wait until the
update is done.
This part struck me particularly because most of our queries will be updates rather than inserts. I was wondering if one created a table called foo on which all updates/inserts were carried out and then a view called foo_view (A copy of foo, or perhaps foo and a linkage of several other tables plus foo) on which all selects occurred, would this locking issue still occur?
That is, would SELECT queries on foo_view still have to wait for an update to finish on foo?
Another brief question my colleague asked. Does this affect caching? I.e. if the SELECT is cached will it hit the cache and return results, or will it wait for the lock to finish first?
Your view will experience the same locking as the underlying tables.
From the MySQL Reference page on locking:
MySQL grants table write locks as
follows:
If there are no locks on the table, put a write lock on it.
Otherwise, put the lock request in the write lock queue.
MySQL grants table read locks as
follows:
If there are no write locks on the table, put a read lock on it.
Otherwise, put the lock request in the read lock queue.
It's worth mentioning that this depends on the database engine you are using. MyISAM will follow the steps above and lock the entire table (even if it is split into multiple partitions) where an engine like InnoDB will do row level locking instead.
If you're not reaching the necessary performance benchmarks with MyISAM and you have shown your bottleneck is waiting on table locks via updates, I would suggest changing the storage engine of your table to InnoDB.