Spec-Zone .ru
спецификации, руководства, описания, API
|
Этот раздел объясняет признаки и разрешения для проблем, с которыми обычно встречаются, с MySQL использования приложений, Connector/J.
Вопросы
23.3.15.1: Когда я пытаюсь соединиться с базой данных с MySQL, Connector/J, я получаю следующее исключение:
SQLException: Server configuration denies access to data sourceSQLState: 08001VendorError: 0
23.3.15.2: Мое приложение не бросает SQLException 'Никакой Подходящий Драйвер'. Почему это происходит?
23.3.15.3: Я пытаюсь использовать MySQL, Connector/J в апплете или приложении, и я получаю исключение, подобное:
SQLException: Cannot connect to MySQL server on host:3306.Is there a MySQL server running on the machine/port youare trying to connect to?(java.security.AccessControlException)SQLState: 08S01VendorError: 0
23.3.15.4: У меня есть сервлет/приложение, который хорошо работает в течение дня, и затем прекращает работать быстро
23.3.15.5: Я пытаюсь использовать JDBC 2.0 обновляемых набора результатов, и я получаю исключение, говоря, что мой набор результатов не обновляем.
23.3.15.6: Я не могу соединиться с сервером MySQL, используя Connector/J, и я уверен, что параметры соединения корректны.
23.3.15.7: Я пытаюсь соединиться с моим сервером MySQL в пределах моего приложения, но я получаю следующую ошибку и складываю трассировку:
java.net.SocketExceptionMESSAGE: Software caused connection abort: recv failedSTACKTRACE:java.net.SocketException: Software caused connection abort: recv failedat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.read(Unknown Source)at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1392)at com.mysql.jdbc.MysqlIO.readPacket(MysqlIO.java:1414)at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:625)at com.mysql.jdbc.Connection.createNewIO(Connection.java:1926)at com.mysql.jdbc.Connection.<init>(Connection.java:452)at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:411)
23.3.15.8: Мое приложение развертывается через JBoss, и я использую транзакции, чтобы обработать операторы на базе данных MySQL. Под тяжелыми грузами я получаю ошибку и трассировку стека, но они только происходят после установленного срока тяжелого действия.
23.3.15.9: При
использовании gcj, a java.io.CharConversionException
исключение повышается, работая с определенными символьными последовательностями.
23.3.15.10:
Обновление таблицы, которая содержит первичный ключ, который является также
FLOAT
или соедините первичный ключ, который использует FLOAT
сбои, чтобы обновить таблицу и повышения исключение.
23.3.15.11:
Вы добираетесь ER_NET_PACKET_TOO_LARGE
исключение, даже при том, что двоичный размер
блоба Вы хотите вставить использование JDBC, безопасно ниже max_allowed_packet
размер.
23.3.15.12: Что должно Вы делать, если Вы получаете сообщения об ошибках, подобные следующему: "Отказ линии связи – Последний пакет, отправленный серверу, был несколько X мс назад"?
23.3.15.13:
Почему делает Connector/J не, повторно соединяются с MySQL и переиздают оператор после коммуникационного
отказа, вместо того, чтобы выдать Исключение, даже при том, что я использую autoReconnect
опция строки подключения?
23.3.15.14: Как я могу использовать 3-байтовый UTF8 с Connector/J?
23.3.15.15:
Как может я использовать 4-байтовый UTF8, utf8mb4
с Connector/J?
23.3.15.16:
Используя useServerPrepStmts=false
и определенные кодировки символов могут
привести к повреждению, вставляя BLOB. Как этого можно избежать?
Вопросы и Ответы
23.3.15.1: Когда я пытаюсь соединиться с базой данных с MySQL, Connector/J, я получаю следующее исключение:
SQLException: Server configuration denies access to data sourceSQLState: 08001VendorError: 0
MySQL, Connector/J, должен использовать сокеты TCP/IP, чтобы соединиться с MySQL, поскольку Java не поддерживает Сокеты Домена Unix. Поэтому, когда MySQL, Connector/J, соединяется с MySQL, менеджер безопасности в сервере MySQL будет использовать свои таблицы предоставления, чтобы определить, разрешается ли соединение.
Следует добавить необходимые учетные данные безопасности к серверу MySQL для этого, чтобы произойти, используя
GRANT
оператор к Вашему MySQL Server. См. Раздел
13.7.1.4,"GRANT
Синтаксис", для получения дополнительной
информации.
Тестирование Вашей связи с mysql клиентом командной строки не будет работать, если Вы
не добавите флаг "узла", и используете что-то другое чем localhost
для узла. mysql
клиент командной строки будет использовать сокеты домена Unix, если Вы будете использовать специальное имя
хоста localhost
. Если Вы тестируете связь к localhost
, использовать 127.0.0.1
как имя хоста
вместо этого.
Изменение полномочий и полномочий ненадлежащим образом в MySQL может потенциально заставить Вашу установку сервера не иметь оптимальные свойства безопасности.
23.3.15.2: Мое приложение не бросает SQLException 'Никакой Подходящий Драйвер'. Почему это происходит?
Есть три возможных причины для этой ошибки:
Драйвер Connector/J не находится в Вашем CLASSPATH
,
см. Раздел 22.3.3, "Установка Connector/J".
Формат Вашего соединения, URL является неправильным, или Вы ссылаетесь на несправедливость драйвер JDBC.
При использовании DriverManager, jdbc.drivers
системное свойство не было заполнено с расположением драйвера Connector/J.
23.3.15.3: Я пытаюсь использовать MySQL, Connector/J в апплете или приложении, и я получаю исключение, подобное:
SQLException: Cannot connect to MySQL server on host:3306.Is there a MySQL server running on the machine/port youare trying to connect to?(java.security.AccessControlException)SQLState: 08S01VendorError: 0
Или Вы выполняете Апплет, Ваш сервер MySQL был установлен с "объединяющим в сеть пропуск" набором опции, или у Вашего сервера MySQL есть брандмауэр, находящийся перед этим.
Апплеты могут только сделать сетевые соединения назад с машиной, которая выполняет веб-сервер, который служил.class файлам для апплета. Это означает, что MySQL должен работать на той же самой машине (или у Вас должно быть своего рода перенаправление порта) для этого, чтобы работать. Это также означает, что Вы не будете в состоянии протестировать апплеты от своей локальной файловой системы, следует всегда развертывать их к веб-серверу.
MySQL, Connector/J, может только связаться с MySQL, используя TCP/IP, поскольку Java не поддерживает сокеты домена Unix. На передачу TCP/IP с MySQL можно было бы влиять, если бы MySQL был запущен с "объединяющего в сеть пропуск" флага, или если это - firewalled.
Если MySQL был запущен с "объединяющего в сеть пропуск" набора опции (пакет Linux Debian сервера MySQL
делает это например), Вы должны прокомментировать это в файле /etc/mysql/my.cnf
или /etc/my.cnf
. Конечно, Ваш my.cnf
файл мог бы
также существовать в data
каталог Вашего сервера MySQL, или где-либо еще (в
зависимости от того, как MySQL был скомпилирован для Вашей системы). Всегда заглядывают двоичные файлы,
создаваемые нами /etc/my.cnf
и
. Если Ваш сервер MySQL был firewalled, Вам
должны будут сконфигурировать брандмауэр, чтобы позволить соединения TCP/IP от узла, куда Ваш код Java работает
к серверу MySQL на порту, который MySQL слушает (по умолчанию, 3306). datadir
/my.cnf
23.3.15.4: У меня есть сервлет/приложение, который хорошо работает в течение дня, и затем прекращает работать быстро
MySQL закрывает соединения после 8 часов неактивности. Вы или должны использовать пул соединения, который
обрабатывает устарелые соединения, или используйте autoReconnect
параметр (см. Раздел
22.3.5.1, "Имена классов Драйвера/Источника данных, Синтаксис URL и Свойства Конфигурации для
Connector/J").
Кроме того, выгода SQLExceptions
в Вашем приложении и соглашении с ними, вместо
того, чтобы распространить их полностью до Ваших выходов приложения. Это - только хорошая практика
программирования. MySQL, Connector/J, установит SQLState
(см. java.sql.SQLException.getSQLState()
в Ваших документах API) к 08S01
когда это встречается с проблемами сетевой связи во время обработки
запроса. Попытка повторно соединиться с MySQL в этой точке.
Следующий (упрощенный) пример показывает то, что кодирует, который может обработать эти исключения, мог бы быть похожим:
Пример 22.12. Connector/J: Пример транзакции с логикой повторной попытки
public void doBusinessOp() throws SQLException { Connection conn = null; Statement stmt = null; ResultSet rs = null; // // How many times do you want to retry the transaction // (or at least _getting_ a connection)? // int retryCount = 5; boolean transactionCompleted = false; do { try { conn = getConnection(); // assume getting this from a // javax.sql.DataSource, or the // java.sql.DriverManager conn.setAutoCommit(false); // // Okay, at this point, the 'retry-ability' of the // transaction really depends on your application logic, // whether or not you're using autocommit (in this case // not), and whether you're using transactional storage // engines // // For this example, we'll assume that it's _not_ safe // to retry the entire transaction, so we set retry // count to 0 at this point // // If you were using exclusively transaction-safe tables, // or your application could recover from a connection going // bad in the middle of an operation, then you would not // touch 'retryCount' here, and just let the loop repeat // until retryCount == 0. // retryCount = 0; stmt = conn.createStatement(); String query = "SELECT foo FROM bar ORDER BY baz"; rs = stmt.executeQuery(query); while (rs.next()) { } rs.close(); rs = null; stmt.close(); stmt = null; conn.commit(); conn.close(); conn = null; transactionCompleted = true; } catch (SQLException sqlEx) { // // The two SQL states that are 'retry-able' are 08S01 // for a communications error, and 40001 for deadlock. // // Only retry if the error was due to a stale connection, // communications problem or deadlock // String sqlState = sqlEx.getSQLState(); if ("08S01".equals(sqlState) || "40001".equals(sqlState)) { retryCount -= 1; } else { retryCount = 0; } } finally { if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { // You'd probably want to log this... } } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { // You'd probably want to log this as well... } } if (conn != null) { try { // // If we got here, and conn is not null, the // transaction should be rolled back, as not // all work has been done try { conn.rollback(); } finally { conn.close(); } } catch (SQLException sqlEx) { // // If we got an exception here, something // pretty serious is going on, so we better // pass it up the stack, rather than just // logging it... throw sqlEx; } } } } while (!transactionCompleted && (retryCount > 0));}
Использование autoReconnect
опция не рекомендуется, потому что нет
никакого надежного метода пересоединения с сервером MySQL, не рискуя некоторым повреждением состояния
соединения или информации о состоянии базы данных. Вместо этого используйте пул соединения, который позволит
Вашему приложению соединиться с сервером MySQL, используя доступное соединение от пула. autoReconnect
средство осуждается, и может быть удалено в будущем выпуске.
23.3.15.5: Я пытаюсь использовать JDBC 2.0 обновляемых набора результатов, и я получаю исключение, говоря, что мой набор результатов не обновляем.
Поскольку у MySQL нет идентификаторов строки, MySQL, Connector/J, может только обновить наборы результатов, которые прибыли из запросов на таблицах, у которых есть по крайней мере один первичный ключ, запрос должен выбрать каждый столбец первичного ключа, и запрос может только охватить одну таблицу (то есть, никакие соединения). Это обрисовывается в общих чертах в спецификации JDBC.
Отметьте, что эта проблема только происходит при использовании обновляемых наборов результатов, и вызывается,
потому что Connector/J неспособен гарантировать, что это может идентифицировать корректные строки в пределах
набора результатов, который будет обновлен, не имея уникальную ссылку на каждую строку. Нет никакого требования,
чтобы иметь уникальное поле на таблице, если Вы используете UPDATE
или DELETE
операторы на таблице, где можно индивидуально определить критерии,
которые будут соответствующими, используя a WHERE
пункт.
23.3.15.6: Я не могу соединиться с сервером MySQL, используя Connector/J, и я уверен, что параметры соединения корректны.
Удостоверьтесь что skip-networking
опция не была включена на Вашем сервере. Connector/J должен быть в
состоянии связаться с Вашим сервером по TCP/IP; названный сокетами не поддерживаются. Также гарантируйте, что Вы
не пропускаете соединения через брандмауэр или другую систему сетевой безопасности. Для получения дополнительной
информации см. Раздел C.5.2.2,"Can't connect to [local] MySQL server
".
23.3.15.7: Я пытаюсь соединиться с моим сервером MySQL в пределах моего приложения, но я получаю следующую ошибку и складываю трассировку:
java.net.SocketExceptionMESSAGE: Software caused connection abort: recv failedSTACKTRACE:java.net.SocketException: Software caused connection abort: recv failedat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.read(Unknown Source)at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1392)at com.mysql.jdbc.MysqlIO.readPacket(MysqlIO.java:1414)at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:625)at com.mysql.jdbc.Connection.createNewIO(Connection.java:1926)at com.mysql.jdbc.Connection.<init>(Connection.java:452)at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:411)
Ошибка, вероятно, указывает, что Вы используете более старую версию Connector/J JDBC драйвер (2.0.14 или 3.0.x), и Вы пытаетесь соединиться с сервером MySQL с версией 4.1x или более новый. Более старые драйверы не являются совместимыми с 4.1 или более новыми из MySQL, поскольку они не поддерживают более новые механизмы аутентификации.
Вероятно, что более старая версия драйвера Connector/J существует в пределах Вашего каталога приложения или
Вашего CLASSPATH
включает более старый пакет Connector/J.
23.3.15.8: Мое приложение развертывается через JBoss, и я использую транзакции, чтобы обработать операторы на базе данных MySQL. Под тяжелыми грузами я получаю ошибку и трассировку стека, но они только происходят после установленного срока тяжелого действия.
Это - JBoss, не Connector/J, проблема и соединяется с использованием транзакций. Под тяжелыми грузами может увеличиться время, потраченное для транзакций, чтобы завершиться, и ошибка вызывается, потому что Вы превысили предопределенный тайм-аут.
Можно увеличить значение тайм-аута, устанавливая TransactionTimeout
припишите TransactionManagerService
в пределах /conf/jboss-service.xml
файл (пред4.0.3) или /deploy/jta-service.xml
для JBoss 4.0.3 или позже. См.
23.3.15.9: При использовании gcj, a java.io.CharConversionException
исключение повышается, работая с определенными
символьными последовательностями.
Это - известная проблема с gcj, который повышает исключение, когда
он достигает неизвестного символа, или один он не может преобразовать. Добавить useJvmCharsetConverters=true
к Вашей строке подключения, чтобы вызвать преобразование символов за пределами gcj библиотек, или попробовать различный JDK.
23.3.15.10: Обновление таблицы, которая содержит первичный ключ,
который является также FLOAT
или соедините первичный ключ, который использует FLOAT
сбои, чтобы обновить таблицу и повышения исключение.
Connector/J добавляет условия к WHERE
пункт во время UPDATE
проверять старые значения первичного ключа. Если там не идет ни в какое
сравнение, то Connector/J считает это условием отказа и повышает исключение.
Проблема состоит в том, что округление различий между предоставленными значениями и значениями, сохраненными в базе данных, может означать, что значения никогда не соответствуют, и следовательно сбои обновления. Проблема будет влиять на все запросы, не только тех от Connector/J.
Чтобы предотвратить эту проблему, используйте первичный ключ, который не использует FLOAT
. Если необходимо использовать столбец с плавающей точкой в своем первичном
ключе, использовать DOUBLE
или DECIMAL
типы вместо FLOAT
.
23.3.15.11: Вы добираетесь ER_NET_PACKET_TOO_LARGE
исключение, даже при том, что двоичный размер блоба Вы
хотите вставить использование JDBC, безопасно ниже max_allowed_packet
размер.
Это то, потому что hexEscapeBlock()
метод в com.mysql.jdbc.PreparedStatement.streamToBytes()
май почти удваивает размер Ваших данных.
23.3.15.12: Что должно Вы делать, если Вы получаете сообщения об ошибках, подобные следующему: "Отказ линии связи – Последний пакет, отправленный серверу, был несколько X мс назад"?
Вообще говоря, эта ошибка предполагает, что сетевое соединение было закрыто. Может быть несколько первопричин:
Брандмауэры или маршрутизаторы могут пресечь неактивные соединения (протокол клиента/сервера MySQL не проверяет с помощью ping-запросов).
MySQL Server может закрывать неактивные соединения, которые превышают wait_timeout
или interactive_timeout
порог.
Чтобы помочь диагностировать эти проблемы, следующие советы могут использоваться. Если недавнее (5.1.13 +) версия Connector/J будет использоваться, то Вы будете видеть улучшенный уровень информации по сравнению с более ранними версиями. Более старые версии просто выводят на экран в прошлый раз, когда пакет был отправлен серверу, который часто является несколько 0 мс назад. Это имеет ограниченное использование, поскольку может случиться так, что пакет был только отправлен, в то время как пакет от сервера не получался в течение нескольких часов. Зная промежуток времени, так как последний Connector/J получил пакет от сервера, полезная информация, так, если это не выводится на экран в Вашем сообщении об исключительной ситуации, рекомендуется, чтобы Вы обновили Connector/J.
Далее, если время, пакет был последним, отправило/получило, превышает wait_timeout
или interactive_timeout
порог, это отмечается в сообщении об исключительной
ситуации.
Хотя сетевые соединения могут быть энергозависимыми, следующее может быть полезным в уходе от проблем:
Гарантируйте, что соединения допустимы когда использующийся от пула соединения.
Используйте запрос, который запускается с /* ping */
выполнить легкий ping
вместо полного запроса. Отметьте, синтаксис ping должен быть точно как определен здесь.
Минимизируйте продолжительность, объект соединения оставляют неактивным, в то время как другая логика приложения выполняется.
Явно проверьте соединения перед использованием этого, если соединение оставили неактивным в течение длительного периода времени.
Гарантируйте это wait_timeout
и interactive_timeout
устанавливаются достаточно высоко.
Гарантируйте это tcpKeepalive
включается.
Гарантируйте, что любой конфигурируемый брандмауэр или настройки тайм-аута маршрутизатора учитывают максимальное ожидаемое время простоя соединения.
Не ожидайте быть в состоянии снова использовать соединение без проблем, если у него будет быть простаивающим в течение периода. Если соединение должно быть снова использовано будучи неактивным в течение какого-либо отрезка времени, гарантировать, что Вы явно тестируете это прежде, чем снова использовать это.
23.3.15.13: Почему делает Connector/J не, повторно соединяются с MySQL и переиздают оператор после
коммуникационного отказа, вместо того, чтобы выдать Исключение, даже при том, что я использую autoReconnect
опция строки подключения?
Есть несколько причин этого. Первой является транзакционная целостность. MySQL Reference Manual утверждает, что "нет никакого надежного метода пересоединения с сервером MySQL, не рискуя некоторым повреждением состояния соединения или информации о состоянии базы данных". Рассмотрите следующую серию операторов например:
conn.createStatement().execute( "UPDATE checking_account SET balance = balance - 1000.00 WHERE customer='Smith'");conn.createStatement().execute( "UPDATE savings_account SET balance = balance + 1000.00 WHERE customer='Smith'");conn.commit();
Рассмотрите случай где соединение со сбоями сервера после UPDATE
к checking_account
. Если никакое исключение не будет выдано, и приложение никогда не
узнает о проблеме, то оно будет продолжать выполняться. Однако, сервер не фиксировал первую транзакцию в этом
случае, так, чтобы откатывался. Но выполнение продолжается со следующей транзакцией, и увеличивается savings_account
баланс 1000. Приложение не получало исключение, таким образом,
оно продолжалось независимо, в конечном счете фиксируя вторую транзакцию, поскольку фиксация только применяется
к изменениям, произведенным в новом соединении. А не передача, имеющая место, депозит был сделан в этом примере.
Отметьте то выполнение с autocommit
включенный не решает эту проблему. Когда
Connector/J встречается с проблемой коммуникации, нет никакого средства определить ли сервер, обработанный в
настоящий момент выполняющийся оператор или нет. Следующие теоретические состояния одинаково возможны:
Сервер, никогда получаемый оператор, и поэтому никакая связанная обработка, произошел на сервере.
Сервер, полученный оператор, выполняемый, это полностью, но ответ не было получено клиентом.
Если Вы работаете с autocommit
включенный, не возможно гарантировать состояние
данных на сервере, когда с коммуникационным исключением встречаются. Оператор, возможно, достиг сервера, или это
не может. Все, что Вы знаете, то, что передача, отказавшая в некоторый момент перед клиентом полученное
подтверждение (или данные) от сервера. Это не только влияет autocommit
операторы
все же. Если проблема коммуникации произошла во время Connection.commit()
, вопрос
возникает того, фиксировалась ли транзакция на сервере перед передачей, отказавшей, или ли сервер, полученный
запрос фиксации вообще.
Вторая причина генерации исключений - определяющие контекст транзакцией контекстные данные могут быть уязвимыми, например:
Временные таблицы.
Определяемые пользователем переменные.
Сторона сервера подготовленные операторы.
Эти элементы теряются, когда связь прерывается, и если соединение тихо повторно соединяется, не генерируя исключение, это могло бы быть вредно для корректного выполнения Вашего приложения.
В сводке коммуникационные ошибки генерируют условия, которые могут хорошо быть опасны для Connector/J просто проигнорировать, тихо повторно соединяясь. Необходимо для приложения быть уведомленным. Это тогда для разработчика приложений, чтобы решить, как продолжить в случае ошибок соединения и отказов.
23.3.15.14: Как я могу использовать 3-байтовый UTF8 с Connector/J?
Использовать 3-байтовый UTF8 с набором Connector/J characterEncoding=utf8
и набор
useUnicode=true
в строке подключения.
23.3.15.15: Как может я использовать 4-байтовый UTF8, utf8mb4
с
Connector/J?
Чтобы использовать 4-байтовый UTF8 с Connector/J конфигурируют сервер MySQL с character_set_server=utf8mb4
.
Connector/J будет тогда использовать ту установку пока characterEncoding
не был
установлен в строке подключения. Это эквивалентно автоматическому обнаружению набора символов.
23.3.15.16: Используя useServerPrepStmts=false
и определенные
кодировки символов могут привести к повреждению, вставляя BLOB. Как этого можно избежать?
При использовании определенных кодировок символов, таких как SJIS, CP932, и BIG5, возможно, что данные BLOB содержат символы, которые могут быть интерпретированы как управляющие символы, например, наклонная черта влево, '\'. Это может привести к поврежденным данным, вставляя BLOB в базу данных. Есть две вещи, которые должны быть сделаны, чтобы избежать этого:
Установите опцию строки подключения useServerPrepStmts
к true
.
Набор SQL_MODE
к NO_BACKSLASH_ESCAPES
.