Question

I have a table with more than 160 milion of entries, which has a wrong table engine, so I'm going to change the engine. When I do this without any preparation, I get a error due to my buffer size, because of too many row locks

mysql> ALTER TABLE foobar ENGINE=MyISAM;
ERROR 1206 (HY000): The total number of locks exceeds the lock table size

I now want to lock the whole table before this action and unlock the whole table afterwards.

mysql> LOCK TABLES foobar WRITE;

My question: Does the mysql server notice that a table lock is already active and skip the row locks or has it locked the table and will now also lock every row again and I will experience the same error again?

I am also open for any other sugestions how to change the engine of such a big (and bigger) table the quickest way :)

Était-ce utile?

La solution

You can run an experiment:

In the first session run:

mysql> LOCK TABLE foobar WRITE;
mysql> ALTER TABLE foobar ENGINE=MyISAM;

In a second session (i.e. open a second terminal window), run:

mysql> SHOW ENGINE INNODB STATUS\G

Down in the TRANSACTIONS section, you'll find your ALTER thread in progress:

---TRANSACTION 69638, ACTIVE 45 sec fetching rows
mysql tables in use 1, locked 1
14626 lock struct(s), heap size 1898936, 5145657 row lock(s)

Whoah! It's creating many individual row locks, in spite of the LOCK TABLE in effect.

(That's just an example; you'll see the number of row locks increasing over time as the ALTER TABLE works through your table.)


So you need to guarantee space for a large number of row locks.

https://dev.mysql.com/doc/refman/5.6/en/innodb-error-codes.html says:

  • 1206 (ER_LOCK_TABLE_FULL)

    The total number of locks exceeds the amount of memory InnoDB devotes to managing locks. To avoid this error, increase the value of innodb_buffer_pool_size. Within an individual application, a workaround may be to break a large operation into smaller pieces. For example, if the error occurs for a large INSERT, perform several smaller INSERT operations.

(emphasis mine)

Also read How much memory Innodb locks really take?

Innodb row level locks are implemented by having special lock table, located in the buffer pool where small record allocated for each hash and for each row locked on that page bit can be set. This in theory can give overhead as low as few bits per row.

So locking 160 million rows requires about 60-80MB of space in the lock table. Your buffer pool might be too small to hold that.

The default size of the InnoDB buffer pool was only 8MB in MySQL 5.1.27 and earlier. The default was increased to 128MB in MySQL 5.1.28.


Re your comment:

every tool does its job ey ;) - so does MyISAM

MyISAM doesn't support Atomicity, Consistency, Isolation, or Durability. Other than that, it's great. :-)

Autres conseils

Normally, if your InnoDB buffer pool isn't large enough to hold row locks for all the rows in a table (as is sometimes necessary), you increase the InnoDB buffer pool size (innodb_buffer_pool_size).

Try increasing your innodb_buffer_pool_size to 128 MB.

If you're still having problems, you can always try creating the new MyISAM table then do INSERT INTO ... SELECT FROM ... to copy your data from the InnoDB table to the MyISAM one. You can copy the rows in chunks to reduce the row locks.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top