powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Как работает jdbc?
13 сообщений из 38, страница 2 из 2
Как работает jdbc?
    #39711553
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вадя,

Не забывай про консистентность.
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711861
Фотография Dmitry.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
интересно...

процедура:

Код: sql
1.
2.
3.
4.
5.
6.
CREATE PROCEDURE test.multi() BEGIN
  do sleep(3);
  SELECT 1 as id, 'hello1' as txt;
  do sleep(3);
  SELECT 2 as id2, 'hello2' as txt2;
END




груви (ну почти жава)

Код: 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.
@GrabConfig(systemClassLoader = true)
@GrabResolver(name='bintray-jcenter', root='http://jcenter.bintray.com/')
@Grab(group='mysql', module='mysql-connector-java', version='8.0.12')

import groovy.sql.Sql;

def parms=[
    useSSL:false,
    //useUnbufferedInput:false,
    //useReadAheadInput:false,
    //maintainTimeStats:false,
    traceProtocol:true
].collect{k,v->"$k=$v"}.join('&')

def sql = Sql.newInstance("jdbc:mysql://192.168.99.100:32777/test?"+parms, "root", "1", "com.mysql.cj.jdbc.Driver")

def cs = sql.connection.prepareCall("{call multi()}")
boolean isResultSet = cs.execute()

while(isResultSet){
    println "---- ${new Date()} got resultset ----"
    def rs = cs.getResultSet()
    while (rs.next()) {
        println rs.toRowResult().toString()
    }
    rs.close()
    isResultSet = cs.getMoreResults()
}
cs.close()
sql.close()



оба резалтсета действительно выдаются одновременно.
но когда я добавил в урл параметр traceProtocol=true
то в логе увидел что второй результат приходит как надо - через 3 секунды но jdbc в mysql так написан...
пытался отключить read-ahead но не помогло...

кусок лога трейса - в последней строке начинает читать второй резалтсет:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Tue Oct 02 17:05:33 EEST 2018 TRACE: ReadAheadInputStream.readIfNecessary([0, 0, 0, 0, 0, 0, 0, 0, 0],0,9)
Tue Oct 02 17:05:33 EEST 2018 TRACE: readPacket() payload:
01 31 06 68 65 6c 6c 6f     . 1 . h e l l o
31                          1

Tue Oct 02 17:05:33 EEST 2018 TRACE: ReadAheadInputStream.readIfNecessary([0, 0, 0, 0],0,4)
Tue Oct 02 17:05:33 EEST 2018 TRACE: Reading packet of length 7
Packet header:
07 00 00 05                 . . . .

Tue Oct 02 17:05:33 EEST 2018 TRACE: ReadAheadInputStream.readIfNecessary([0, 0, 0, 0, 0, 0, 0],0,7)
Tue Oct 02 17:05:33 EEST 2018 TRACE: readPacket() payload:
fe 00 00 0a 00 00 00        . . . . . . .

Tue Oct 02 17:05:33 EEST 2018 TRACE: ReadAheadInputStream.readIfNecessary([0, 0, 0, 0],0,4) not all data available in buffer, must read from stream
Tue Oct 02 17:05:33 EEST 2018 TRACE:   ReadAheadInputStream.fill(4), buffer_size=16384, current_position=0, need to read 4 bytes to fill request, attempting to read 4 bytes.
Tue Oct 02 17:05:36 EEST 2018 TRACE: Reading packet of length 1


...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711865
pavel_nv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного покопался,
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-implementation-notes.html
Код: java
1.
cs.setFetchSize(Integer.MIN_VALUE);


Позволяет получить первый ResultSet сразу, но в этому случае не получилось получить после этого второй.
На работе с ораклом вроде такой проблемы нету.
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711885
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
странно всё это....
как-то не экономично все это ...
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711908
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А сделать в хранимке:
Код: plsql
1.
2.
3.
select ...
union
select ...

превратив две выборки в одну?
Или я чего-то не понимаю?
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711919
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovА сделать в хранимке:
Код: plsql
1.
2.
3.
select ...
union
select ...


превратив две выборки в одну?
Или я чего-то не понимаю?
превратятся, а в чём будет профит?
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711921
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

результат будет тот же - вернутся записи после выполнения всех селектов, что и есть сейчас
+ куча неудобств
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711935
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А какая польза в это всем?
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711937
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если заказана/требуется сортировка, то сервер сначала получит весь набор данных и только потом начнёт возвращать результат клиенту.
Если сортировки не требуются, то возможны варианты.

P.S.
Профит в том, что не надо делать ту работу, которую сервер БД в состоянии сделать без вашего вмешательства.
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711968
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,
не, тут совсем не это....
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39711985
pavel_nv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
CREATE PROCEDURE `new_procedure`()
BEGIN
select * from t;
select * from (select 'abc') data where sleep(1) = 0;
END



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
        log.info("start...");
        jdbcTemplate.execute(conn -> {
            CallableStatement pstmt = conn.prepareCall("{call new_procedure()}");
            pstmt.setFetchSize(Integer.MIN_VALUE);
            return pstmt;
        }, (CallableStatementCallback<?>) cs -> {
            cs.execute();
            log.info("executed");
            ResultSet rs = cs.getResultSet();
            ResultSetImpl nativeResultset = rs.unwrap(ResultSetImpl.class);

            while (nativeResultset.next()) {
                log.info("first {}", nativeResultset.getObject(1));
            }

            ResultSet nextResultSet = (ResultSet) nativeResultset.getNextResultset();

            while (nextResultSet.next()) {
                log.info("second {}", nextResultSet.getObject(1));
            }
            return null;
        });



Логи:
2018-10-02 19:23:21.752 INFO 21494 --- [ main] start...
2018-10-02 19:23:21.858 INFO 21494 --- [ main] executed
2018-10-02 19:23:21.858 INFO 21494 --- [ main] first 1
...
2018-10-02 19:23:21.860 INFO 21494 --- [ main] first 3
2018-10-02 19:23:23.858 INFO 21494 --- [ main] second abc

А чего через JDBC апи не работает... толи фича, толи баг
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39712142
Фотография Dmitry.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это работает

Код: java
1.
cs.setFetchSize(Integer.MIN_VALUE);



но первый

Код: java
1.
rs.close()



кидает SQLException: Attempt to close streaming result set com.mysql.cj.protocol.a.result.ResultsetRowsStreaming@2e8e8225 that was not registered.

закоментил rs.close() - падает с тем-же ексепшином на следующем методе.

взял rs.close() в try-catch игнорируя ексепшн

и все заработало - фетчит все по мере получения!

явная бага в драйвере
...
Рейтинг: 0 / 0
Как работает jdbc?
    #39712188
вадя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry.,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
ResultSet

По умолчанию ResultSets полностью извлекаются и сохраняются в памяти. В большинстве случаев это наиболее
эффективный способ работы и, благодаря дизайну сетевого протокола MySQL, проще реализовать. Если вы 
работаете с ResultSets, которые имеют большое количество строк или больших значений, и не могут выделить 
кучу пространства в вашей JVM для требуемой памяти, вы можете сообщить драйверу передать результаты 
обратно по одной строке за раз.

Чтобы включить эту функцию, создайте Statementэкземпляр следующим образом:

 [code=sql]
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
              java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);


Комбинация набора результатов только для чтения, доступного только для чтения, с размером выборки
Integer.MIN_VALUE служит в качестве сигнала к результату набора строк для последовательности строк. После
этого любые результирующие наборы, созданные с помощью инструкции, будут загружаться по строкам.

С этим подходом есть некоторые оговорки. Вы должны прочитать все строки в результирующем наборе (или
закрыть его), прежде чем вы сможете выдать какие-либо другие запросы в соединении, или будет выбрано
исключение.

Самые ранние блокировки этих операторов могут быть освобождены (будь то MyISAMблокировки на уровне
таблицы или блокировки на уровне строк в каком-либо другом хранилище, например InnoDB, когда это
завершено).

Если оператор находится в пределах объема транзакции, блокировки освобождаются при завершении
транзакции (что подразумевает, что оператор должен выполнить сначала). Как и в большинстве других баз
данных, операторы не заполняются до тех пор, пока не будут прочитаны все ожидающие ответа результаты,
или активный набор результатов для оператора закрыт.

Поэтому, используя результаты потоковой передачи, обрабатывайте их как можно быстрее, если вы хотите
поддерживать параллельный доступ к таблицам, на которые ссылается оператор, создающий набор
результатов.

Другой альтернативой является использование потоковой передачи на основе курсора для получения
заданного количества строк каждый раз. Это можно сделать, установив для свойства соединения
useCursorFetchзначение true, а затем вызывая setFetchSize(int)с intжелаемым количеством строк, которые будут
извлекаться каждый раз:

Код: sql
1.
2.
3.
4.
conn = DriverManager.getConnection("jdbc:mysql://localhost/?useCursorFetch=true", "user", "s3cr3t");
stmt = conn.createStatement();
stmt.setFetchSize(100);
rs = stmt.executeQuery("SELECT * FROM your_table_here");


как бы получается такой вариант тоже не очень хороший. особенно при больших результатах селекта...
...
Рейтинг: 0 / 0
13 сообщений из 38, страница 2 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / Как работает jdbc?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]