URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 8478
[ Назад ]

Исходное сообщение
"проблема с InnoDB"

Отправлено zznmga , 14-Окт-09 02:22 
Вопросик по InnoDB

Использую mysql 5.1.26
ОС : FreeBSD server.domain.com 6.3
ОЗУ : 3 Гига
Захотел я потестить InnoDB и столкнулся с проблемой.

Создал я таблицу на 100000 записей, структура такова :

mysql> describe accounts;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| username | varchar(32) | NO   |     | NULL    |                |
| password | varchar(32) | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
3 rows in set (0.16 sec)


Запускаю приложение, которое подключается к серверу бд, выгребает первую запись и удаляет ее и ждет 5-10 секунд и продолжает.
Обращения есс-но идут к таблице вышеприведенной.

Перечень запросов таков :

START TRANSACTION
SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE
проверяю то что вернулось , если все ок, то
DELETE FROM accounts WHERE id=" + result[0]
COMMIT

Если запускать в 10 потоках, то все работает на ура. Пробовал я запускать при 300 потоках - работало минут 10 нормально (обработало 30к записей), а потом
таблица залочилась :(

В show processlist вот такое :

| 46046 | root | localhost | dev  | Query   |  768 | Sending data | SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE |
| 46047 | root | localhost | dev  | Query   |  767 | Sending data | SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE |
| 46048 | root | localhost | dev  | Query   |  767 | Sending data | SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE |
| 46049 | root | localhost | dev  | Query   |  767 | Sending data | SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE |
| 46050 | root | localhost | dev  | Query   |  767 | Sending data | SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE |
| 46059 | root | localhost | dev  | Query   |    0 | NULL         | show processlist                                               |
+-------+------+-----------+------+---------+------+--------------+----------------------------------------------------------------+
367 rows in set (0.00 sec)

В логах мускула никах эксепшинов нету.

Может что то с настройками Innodb нето ?
Вот как у меня :

# Uncomment the following if you are using InnoDB tables
innodb_data_home_dir = /usr/local/mysql/data/
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /usr/local/mysql/data/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
innodb_buffer_pool_size = 256M
innodb_additional_mem_pool_size = 20M
# Set .._log_file_size to 25 % of buffer pool size
innodb_log_file_size = 64M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50


Как это побороть что бы таблица не лочилась ?

Можете предложить какие значения должны быть, что бы работало хотя бы при 300-500 потоков и не лочилось ?

Заранее благодарен.


Содержание

Сообщения в этом обсуждении
"проблема с InnoDB"
Отправлено Michael , 14-Окт-09 09:46 

>Использую mysql 5.1.26

попробуйте для начала обновиться до последней версии.
5.1.26 не была стабильной и в принципе не предназначена для использования в продакшене


"проблема с InnoDB"
Отправлено svn , 14-Окт-09 09:54 
>Перечень запросов таков :
>
>START TRANSACTION
>SELECT id, username, password FROM accounts LIMIT 1 FOR UPDATE
>проверяю то что вернулось , если все ок, то
>DELETE FROM accounts WHERE id=" + result[0]
>COMMIT

FOR UPDATE блокирует всю таблицу, а уже потом количество строк ограничивается до 1. Это весьма чётко отражено в документации.


>Можете предложить какие значения должны быть, что бы работало хотя бы при
>300-500 потоков и не лочилось ?

Очень большое число потоков. Надо использовать оптимистичные блокировки.
Например так.

1. SELECT id, username, password FROM accounts WHERE locked=false LIMIT 1
2. UPDATE accounts SET locked=true WHERE id = <id из первого запроса> AND locked=false
3. проверить если rows_updated<1 перейти к шагу 1
4. делай свои проверки
5. DELETE FROM accounts WHERE id = <id из первого запроса>



"проблема с InnoDB"
Отправлено zznmga , 14-Окт-09 14:21 

>Очень большое число потоков. Надо использовать оптимистичные блокировки.

А что такое "оптимистичные блокировки" ? И что за locked в "WHERE locked=false". Вообще эта конструкция к innodb относится или к myisam ?


"проблема с InnoDB"
Отправлено svn , 14-Окт-09 14:40 
>И что за locked в "WHERE locked=false".

Добавь поле в таблицу.

>Вообще эта конструкция к innodb относится или к myisam ?

Ни к тому ни к другому. Это обычный sql.


"проблема с InnoDB"
Отправлено zznmga , 14-Окт-09 15:53 
>>И что за locked в "WHERE locked=false".
>
>Добавь поле в таблицу.
>
>>Вообще эта конструкция к innodb относится или к myisam ?

Спасибо огромное, я понял суть вашего примера. Только одного не могунайти, это как получить значение  rows_updated  после UPDATE запроса в Mysql.


"проблема с InnoDB"
Отправлено zznmga , 14-Окт-09 16:01 
>>>И что за locked в "WHERE locked=false".
>>
>>Добавь поле в таблицу.
>>
>>>Вообще эта конструкция к innodb относится или к myisam ?
>
>Спасибо огромное, я понял суть вашего примера. Только одного не могунайти, это
>как получить значение  rows_updated  после UPDATE запроса в Mysql.

отвечаю сам себе : mysql_affected_rows  :)

буду пробовать , спасибо svn