|
|
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
Если sql-запрос выполняется долго, то иногда хочется его отменить. Но, сюрприз! mysql jdbc коннекор сделан на old сокетах, а они не понимают, если им зовешь Thread.interrupt(). То, что я пока выяснил - это то, что есть метод Statement.cancel(), позволяющий, если драйвер может, отменять выполнение текущего запроса из другого потока. Но как-то это все равно криво. А что делать, если точного объекта Statement нету? Мы ведь можем работать с ORM, кроме того, в другом потоке могут быть сотни разных Statement-ов, какому дергать cancel? Вобщем, Statement есть не всегда. Мне бы отменить весь поток, например. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. У mysql jdbc драйвера есть SocketFactory и у класса Socket есть SocketImplFactory, вот туда бы в одно из мест этих засунуть имплементацию, которая умеет бросать InterrupertException. Но навскидку, таких либ найти не удалось. Не знаю, может есть еще какой-то способ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2016, 18:17 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2016, 18:34 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2016, 18:35 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
Придумал. В драйвере есть параметр socketFactory. У SocketChannel которое из nio есть метод socket(), который возвращает сокет, соответствующий каналу... Как-то так: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Странно, что по умолчанию коннектор пользуется старыми сокетами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2016, 21:23 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
вадя http://dev.mysql.com/doc/refman/5.7/en/kill.html Кстати, Statement.cancel() в JDBC драйвере MySQL именно это и делает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.02.2016, 23:48 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
Мдя, утром оказалось, что вышеприведенного решения недостаточно. 1. Без исплонения Statement.cancel() запрос все равно остается на исполнении в базе, даже если сокет бросает InterruptedException. 2. Если коннекшен достается из пула, то пулу может от такого порвать шаблон. HikariCP ругается. 3. если из сокетового read() было брошено InterruptedException, то не факт, что такой сокет можно дальше использовать. Предположительно, после такого этот сокет использовать нельзя. Вроде, судя по ваершакру, такой сокет финализируется. По этой причине, исполнение Statement.cancel() в блоке finally или в catch в том же потоке, который надо прервать, не дает эффекта, потому, что сокет которым мы законекчены к базе, уже бросил InterruptedException и не может больше что-то слать. Кроме того, коннекшены, которые бросили InterruptedException должны удаляться из пула - а не факт, что это происходит, хотя hikariCP должен удалять, по идее. 4. особенность работы mysql состоит в том, что если запрос начал выполняться, то коннекшен можно положить, и запрос отменен не будет. Иногда это хорошо, иногда плохо. То есть Statement.cancel() не "можно", а "всегда нужно" дергать другим потоком. Для этого его туда надо опубликовать, это уже плохо. А иногда все вообще хуже, если у нас например orm, то Statement-а может и не быть... Ну то есть получается, с отменой запросов/потоков с sql все плохо, архитектура не проработана. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 13:45 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
chabapokТо есть Statement.cancel() не "можно", а "всегда нужно" дергать другим потоком. Какая связь между потоком и сокетом? Statement.cancel() в MySQL драйвере открывает новое соединение. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 17:15 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
В общем случае запросы заранее проектируются. Т.е. отмена запроса из области, когда проектировщику нечем занятся. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 21:04 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
chabapokВобщем, Statement есть не всегда.Rollback ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 21:14 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
Локшин МаркКакая связь между потоком и сокетом? Statement.cancel() в MySQL драйвере открывает новое соединение. Ну хз, возможно, Statement.cancel() не может подхватить нужный id, когда соединение уже разорвано. Если подставить драйверу nio-сокет, вызвать InterruptedException и потом из того же потока внутри finally сделать Statement.cancel(), то запрос не отменяется. А если делать из другого потока, то отменяется. Это все, что могу сказать. Как оно там внутри разгребает этот момент я не смотрел. Поскольку mysql имеет некоторое пороговое значение для кол-ва клиентов, то открывание нового соединения может сработать весьма печально - заблокировать на какое-то время поток, в котором делаешь Statement.cancel() В tcp протоколе есть такая штука, как urgent data, и в сокетах жавовских она есть, правда, якобы, не везде реализована. Это кадр длиной 1 байт и высокого приоритета. Посылается по соединению, но не становится в конец очереди отправки, а становится в ее начало. При помощи него обрабатываются такие штуки, как CTRL-C. Если бы они сделали отмену через этот механизм, то было б красивее. Petro123В общем случае запросы заранее проектируются. Т.е. отмена запроса из области, когда проектировщику нечем занятся. В большинстве случаев, да. Но драйвер должен покрывать не большинство случаев, а все. Конкретно я хотел сделать отмену запроса при отвале клиента, только у меня не веб, а legacy софтина с хитрым протоколом. И там отвал клиента - это вполне конкретное событие. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 21:44 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
chabapokВ tcp протоколе есть такая штука, как urgent data, и в сокетах жавовских она есть, правда, якобы, не везде реализована. Это кадр длиной 1 байт и высокого приоритета. Посылается по соединению, но не становится в конец очереди отправки, а становится в ее начало. При помощи него обрабатываются такие штуки, как CTRL-C. Если бы они сделали отмену через этот механизм, то было б красивее. И был бы красивый механизм "отстреливания" запросов на MySQL злоумышленником. К тому же никак не решает проблему с уже разорванным соединением. В PostgeSQL, например, это реализовано более потребно - во время процедуры установления коннекта сервер генерирует 32-битный ключ, посылка которого вместе с кодом команды на порт PostgreSQL (и pid???) отменяет выполняющийся запрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 21:59 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
chabapokВ большинстве случаев, да OK пришли к одному мнению. chabapokНо драйвер должен покрывать не большинство случаев, а все вы драйвер делаете? Драйвер делают для программистов. Согласен, что 0,5 процентов захотт отменять запросы. chabapokКонкретно я хотел сделать отмену запроса при отвале клиента, Это вся цель? Сервер сам всё уберёт при "отвале клинета". Он будт в курсе при этом событии. Т.е. если это драйвер, то удачи! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.02.2016, 22:46 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
Локшин МаркchabapokВ tcp протоколе есть такая штука, как urgent data, И был бы красивый механизм "отстреливания" запросов на MySQL злоумышленником. Ну это смотря как сделать. :) Конечно можно сделать и злоумышленнико-френдли, но можно и нет. Petro123Сервер сам всё уберёт при "отвале клинета". Он будт в курсе при этом событии. Сервер в моем случае представляет из себя велосипед с блэкджеком и шлюпкой :). Но какой-нибудь томкат в силу специфики архитектуры, ничего с базой не сделать не может. Пул может роллбэк сделать, это да - но не более того. Но роллбэк делается уже после того, как все запросы отработали, а речь шла о том, чтобы прибить задачу с несколькими тяжелыми селектами. Petro123Т.е. если это драйвер, то удачи! нет, я о том, что в драйвере такая фича могла бы и быть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2016, 11:45 |
|
||
|
Как решают проблему отмены jdbc-запросов (или всего mysql потока)?
|
|||
|---|---|---|---|
|
#18+
chabapokа речь шла о том, чтобы прибить задачу с несколькими тяжелыми селектами. тут противоречие. По практике, такие задачи не делают...или делают, но очень сильно и плотно работая с сервером. Пул для таких задач тоже не нужен. Т.е. это не стандартные задачи и не стандартная архитектура = индивидуальный конкретный проект с очень длинными запросами. chabapokА что делать, если точного объекта Statement нету? Мы ведь можем работать с ORM, кроме того, в другом потоке могут быть сотни разных Statement-ов, какому дергать cancel? Вобщем, Statement есть не всегда. итого пришли, что нужно не выдумать все случаи, а решать конкретный проект. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.02.2016, 11:53 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=39176958&tid=2124331]: |
0ms |
get settings: |
6ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
157ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
50ms |
get tp. blocked users: |
2ms |
| others: | 243ms |
| total: | 489ms |

| 0 / 0 |
