tags:

views:

2426

answers:

8

Query:

SELECT COUNT(online.account_id) cnt from online;

But online table is also modified by an event, so frequently I can see lock by running show processlist.

Is there any grammar in MySQL that can make select statement not causing locks?

And I've forgotten to mention above that it's on a MySQL slave database.

After I added into my.cnf:transaction-isolation = READ-UNCOMMITTED the slave will meet with error:

 Error 'Binary logging not possible. Message: Transaction level 'READ-UNCOMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'' on query

So, is there a compatible way to do this?

A: 

You may want to read this page of the MySQL manual. How a table gets locked is dependent on what type of table it is.

MyISAM uses table locks to achieve a very high read speed, but if you have an UPDATE statement waiting, then future SELECTS will queue up behind the UPDATE.

InnoDB tables use row-level locking, and you won't have the whole table lock up behind an UPDATE. There are other kind of locking issues associated with InnoDB, but you might find it fits your needs.

zombat
Will "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED" work for MyISAM tables?
Shore
MyISAM tables do not support transactions in any form. A transactional query will run on a MyISAM table, so the query you mention above will execute, but it has no effect.
zombat
Then what can I do to avoid SELECTS queuing up in the case of MyISAM?
Shore
A: 

From this reference:

If you acquire a table lock explicitly with LOCK TABLES, you can request a READ LOCAL lock rather than a READ lock to enable other sessions to perform concurrent inserts while you have the table locked.

McWafflestix
A: 

It sounds like you might be looking for the equivalent of T-SQL's "WITH (nolock)" command. I found an interesting post that covers this here: http://www.sqldba.org/articles/22-mysql-with-nolock.aspx

Hopefully this will help. Good luck.

regex
+1  A: 

If the table is InnoDB, see http://dev.mysql.com/doc/refman/5.1/en/innodb-consistent-read.html -- it uses consistent-read (no-locking mode) for SELECTs "that do not specify FOR UPDATE or LOCK IN SHARE MODE if the innodb_locks_unsafe_for_binlog option is set and the isolation level of the transaction is not set to SERIALIZABLE. Thus, no locks are set on rows read from the selected table".

Alex Martelli
+2  A: 

Use SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

Docs are here.

Chris Lively
Thank you,I think it's near,but how long will this statement take affect?I'm going to use this statement in a PHP programme,and should be best reset TRANSACTION ISOLATION LEVEL automatically once query finished
Shore
A: 

Depending on your table type, locking will perform differently, but so will a SELECT count. For MyISAM tables a simple SELECT count(*) FROM table should not lock the table since it accesses meta data to pull the record count. Innodb will take longer since it has to grab the table in a snapshot to count the records, but it shouldn't cause locking.

You should at least have concurrent_insert set to 1 (default). Then, if there are no "gaps" in the data file for the table to fill, inserts will be appended to the file and SELECT and INSERTs can happen simultaneously with MyISAM tables. Note that deleting a record puts a "gap" in the data file which will attempt to be filled with future inserts and updates.

If you rarely delete records, then you can set concurrent_insert equal to 2, and inserts will always be added to the end of the data file. Then selects and inserts can happen simultaneously, but your data file will never get smaller, no matter how many records you delete (except all records).

The bottom line, if you have a lot of updates, inserts and selects on a table, you should make it InnoDB. You can freely mix table types in a system though.

Brent Baisley
+3  A: 

Found an article titled "MYSQL WITH NOLOCK"

http://www.sqldba.org/articles/22-mysql-with-nolock.aspx

in MSSQL you would do the following:

SELECT * FROM TABLE_NAME WITH (nolock)

and the MYSQL equivalent is

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
Jon Erickson
Thanks,so this will work for Innodb,but what if MyISAM?
Shore
A: 

SELECTs do not normally do any locking that you care about on InnoDB tables. The default transaction isolation level means that selects don't lock stuff.

Of course contention still happens.

MarkR