WebMoney: WMZ Z294115950220 WMR R409981405661 WME E134003968233 |
Visa 4274 3200 2453 6495 |
Эта секция объясняет признаки и решения
для проблем, с которыми обычно сталкиваются с приложениями,
используя MySQL Connector/J. Вопросы и ответы
15.1:
Когда я пытаюсь соединиться с базой данных с MySQL Connector/J, я
получаю следующее исключение: Я могу соединиться клиентом
командной строки MySQL. Connector/J обычно использует сокеты TCP/IP, чтобы соединиться с MySQL
(см. разделы 6.8 и
6.9 для исключений).
Менеджер безопасности на сервере MySQL использует свои таблицы привилегий,
чтобы определить, разрешена ли связь TCP/IP. Необходимо поэтому добавить
необходимые параметры безопасности серверу MySQL для связи командой
Неправильное изменение привилегий и разрешений на MySQL может потенциально
заставить вашу установку сервера иметь неоптимальные свойства безопасности.
Тестирование вашей возможности соединения клиентом командной строки
mysql
не будет работать, если вы не добавите опцию
15.2:
Мое приложение бросает SQLException 'No Suitable Driver'.
Почему это происходит? Есть три возможных причины для этой ошибки: Драйвер Connector/J не находится в вашем
Формат вашей связи URL неправильный, или вы ссылаетесь на
ошибочный драйвер JDBC. Используя DriverManager, системное свойство
15.3:
Я пытаюсь использовать MySQL Connector/J в апплете или приложении, и
получаю исключение, подобное Ваш сервер MySQL был настроен с включенной опцией
Апплеты могут установить сетевые связи только назад с машиной, которая
управляет веб-сервером, который обрабатывает файл .class апплета.
Это означает, что MySQL должен работать на той же самой машине (или у вас
должно быть своего рода переназначение порта). Это также означает, что вы не
будете в состоянии проверить апплеты от своей локальной файловой системы, но
должны всегда развертывать их к веб-серверу. Connector/J обычно использует сокеты TCP/IP, чтобы соединиться с MySQL
normally uses TCP/IP sockets to connect to MySQL
(см. разделы 6.8 и
6.9 для исключений).
Связь TCP/IP с MySQL может быть затронута переменной
15.4:
У меня есть сервлет/приложение, который хорошо работает в течение дня, а
затем прекращает работать в течение ночи. MySQL закрывает связи после 8 часов бездеятельности.
Или необходимо использовать пул связи, который обращается с несвежими
связями, или используйте опцию Кроме того, обработайте Следующий (упрощенный) пример показывает то, что код, который может
обращаться с этими исключениями, мог бы быть похожим на это:
Пример 15.1. Connector/J: Пример транзакции с логикой повторной попытки
Использование опции 15.5:
Я не могу соединиться с сервером MySQL, используя Connector/J, и я уверен,
что параметры связи правильны. Удостоверьтесь, что переменная
15.6:
Приложение развернуто через JBoss, и я использую транзакции, чтобы
обращаться с запросами к базе данных MySQL. Под большими нагрузками я получаю
ошибку и трассировку стека, но они происходят только после установленного
срока тяжелой деятельности. Это проблема JBoss, а не Connector/J, связана с использованием
транзакций. Под большими нагрузками может увеличиться время, потраченное для
транзакций, и ошибка вызывается, потому что вы превысили
предопределенный тайм-аут. Можно увеличить тайм-аут, установив атрибут
15.7:
Обновление таблицы, которая содержит
primary key, который является также
Connector/J добавляет условия к Проблема состоит в том, что округление различий между значениями,
поставляемыми и сохраненными в базе данных, может означать, что
значения никогда не соответствуют, и следовательно обновление терпит неудачу.
Проблема затронет все запросы, а не только от Connector/J. Чтобы предотвратить эту проблему, используйте первичный ключ, который не
использует 15.8:
Я получаю исключение
Это потому, что метод 15.9:
Что делать, если я получаю сообщения об ошибках, подобные следующему:
Communications link failure - Last packet sent to the
server was X ms ago? Вообще говоря, эта ошибка предполагает, что сетевое соединение было
закрыто. Может быть несколько первопричин: Брандмауэры или маршрутизаторы могут пресечь неработающие связи.
MySQL Server может закрывать неработающие связи, которые превышают
Хотя сетевые соединения могут быть изменчивыми, следующее может быть
полезным в предотвращении проблем: Гарантируйте, что связи действительны, когда используются из пула
связи. Используйте запрос, который начинается с
Минимизируйте время, которое объект связи оставляют неработающим, в то
время как другая прикладная логика выполняется. Явно проверьте связь перед использованием, если связь оставили
неработающей в течение длительного периода времени. Гарантируйте, что Гарантируйте, что включена опция
Гарантируйте, что любые конфигурируемые параметры брандмауэра или
маршрутизатора допускают максимальное ожидаемое время простоя связи.
Не ожидайте, что будете в состоянии снова использовать связь без проблем,
если у нее был длительный простой. Если связь должна быть снова использована,
будучи неработающей в течение какого-либо отрезка времени, надо
гарантировать, чтобы вы явно проверили ее прежде, чем снова использовать.
15.10:
Почему не делает Connector/J реконнект с MySQL после сбоя связи вместо того,
чтобы бросить исключение, даже при том, что я использую опцию
Есть несколько причин этого. Первой является целостность транзакций.
Справочник MySQL указывает, что
нет никакого надежного метода повторного подключения к
серверу MySQL, не рискуя повреждением состояния связи или информации о
статусе базы данных. Рассмотрите следующий ряд запросов, например: Рассмотрите случай, где связь с сервером прерывается после
Отметьте, что работа с включенной Сервер никогда не получал запрос, поэтому никакая связанная
обработка не произошла на сервере. Сервер получил запрос, выполнил его полностью, но ответ
не был получен клиентом. Если вы раболтаете с включенной Вторая причина для создания исключений: рассмотренные транзакцией
контекстные данные могут быть уязвимыми, например: Временные таблицы. Пользовательские переменные. Серверная сторона подготовленного запроса. Эти пункты потеряны, когда связь прерывается, и если связь тихо снова
соединяется, не производя исключение, это могло бы быть вредно для
правильного выполнения вашего запроса. Таким образом, ошибки связи производят условия, которые для Connector/J
может быть небезопасно просто проигнорировать, тихо снова соединившись.
Необходимо для приложения обработать ситуацию. Для разработчика приложений
важно решить, как продолжить в случае ошибок связи. 15.11:
Как я могу использовать 3-байтовый UTF8 с Connector/J? 8.0.12 и раньше: чтобы использовать
3-байтовый UTF8 с Connector/J, установите
8.0.13 и позже:
Поскольку нет никакого названия набора символов Java-стиля для
15.12:
Как использовать 4-байтовый UTF8
( Чтобы использовать 4-байтовый UTF8 с Connector/J настройте сервер MySQL с
15.13:
Использование Используя определенные кодировки символов, такие как SJIS, CP932 и BIG5,
возможно, что данные BLOB содержат знаки, которые могут интерпретироваться
как управляющие символы, например, наклонная черта влево, '\'.
Это может привести к испорченным данным, вставляя BLOB в базу данных.
Есть две вещи, которые должны быть сделаны, чтобы избежать этого: Установите опцию строки подключения
Установите
Глава 15. Проблемы с приложениями Connector/J
SQLException: Server configuration denies access to data source
SQLState: 08001
VendorError: 0
GRANT
на вашем сревере MySQL,
см. GRANT Statement.--host
и используете что-то
другое, чем localhost
для хоста. Клиент
mysql
попытается использовать сокет Unix, если вы будете использовать специальное
имя хоста localhost
.
Если вы проверяете возможность соединения TCP/IP к
localhost
, используйте как имя хоста
127.0.0.1
.CLASSPATH
, см.
главу 4.jdbc.drivers
не было задано
с местоположением драйвера Connector/J.
SQLException: Cannot connect to MySQL server on host:3306.
Is there a MySQL server running on the machine/port you
are trying to connect to?
(java.security.AccessControlException)
SQLState: 08S01
VendorError: 0
skip_networking
или у вашего сервера MySQL есть неправильно настроенный брандмауэр.skip_networking
или брандмауэром сервера. Если MySQL был запущен с включенной опцией
skip_networking
,
необходимо закомментировать ее в файле
/etc/mysql/my.cnf
или
/etc/my.cnf
, чтобы включить соединения по
TCP/IP. Обратите внимание на то, что ваш конфигурационный файл сервера мог бы
также существовать в каталоге data
сервера
MySQL или где-то в другом месте, в зависимости от того, как MySQL был собран,
двоичные пакеты Oracle всегда ищут
/etc/my.cnf
и
, см.
Using Option Files. Если ваш сервер MySQL был защищен
брандмауэром, необходимо будет формировать брандмауэр, чтобы позволить связи
TCP/IP от хоста, где работает код Java, к серверу MySQL на порт, который
MySQL слушает (по умолчанию это 3306).datadir
/my.cnfautoReconnect
(см.
раздел 6.3).SQLExceptions
в вашем приложении вместо того, чтобы размножить их полностью до вылета ваших
программ. Это просто хорошая практика программирования. MySQL Connector/J
установит SQLState
(см.
java.sql.SQLException.getSQLState()
в
ваших описаниях API) в 08S01
,
когда это сталкивается с проблемами сетевого соединения во
время обработки запроса.
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
устарела и может быть удалена в будущем выпуске.skip_networking
выключена на
на вашем сервере. Connector/J должен быть в состоянии общаться с вашим
сервером по TCP/IP, именованные сокеты не поддерживаются. Также гарантируйте,
что вы не пропускаете связи через брандмауэр или другую систему защиты сети.
Для получения дополнительной информации посмотрите
Can't connect to [local] MySQL server.TransactionTimeout
в
TransactionManagerService
в файле
/conf/jboss-service.xml
(pre-4.0.3) или /deploy/jta-service.xml
для
JBoss 4.0.3 или позже, см.
TransactionTimeout в JBoss wiki
для получения дополнительной информации.FLOAT
или составным первичным ключом, который использует
FLOAT
,
не обновляет таблицу и поднимает исключение.WHERE
во время UPDATE
, чтобы проверять старые
значения первичного ключа. Если там нет совпадения, то Connector/J
считает это условием неудачи и поднимает исключение.FLOAT
.
Если необходимо использовать столбец с плавающей точкой в первичном ключе,
можно использовать типы
DOUBLE
или
DECIMAL
вместо
FLOAT
.ER_NET_PACKET_TOO_LARGE
даже при том, что размер blob, который я хочу вставить с использованием JDBC,
безопасно ниже размера
max_allowed_packet
.
hexEscapeBlock()
в
com.mysql.cj.AbstractPreparedQuery.streamToBytes()
почти удваивает размер ваших данных.wait_timeout
или
interactive_timeout
./* ping */
для пинга вместо полного запроса.
Отметьте, синтаксис должен быть точно как определен здесь.wait_timeout
и
interactive_timeout
установлены достаточно высоко.tcpKeepalive
.autoReconnect
строки подключения?
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()
, возникает вопрос: была ли
транзакция передана на сервере прежде, чем коммуникация прервалась.characterEncoding=utf8
и
useUnicode=true
в строке подключения.utfmb3
, который можно использовать с опцией
связи charaterEncoding
, единственный способ
использовать utf8mb3
как ваш набор символов
связи, это использовать сопоставление
utf8mb3
(например,
utf8_general_ci
) для опции
connectionCollation
, что вызывает набор символов
utf8mb3
, который будет использоваться. См.
раздел 6.6.utf8mb4
) с Connector/J?character_set_server=utf8mb4
.
Connector/J будет тогда использовать эту настройку, если
characterEncoding
и
connectionCollation
не были установлены в строке
подключения. Это эквивалентно автообнаружению набора символов. Посмотрите
раздел 6.6 для деталей.
8.0.13 позже: можно использовать
characterEncoding=UTF-8
, чтобы использовать
utf8mb4
, даже если
character_set_server
на сервере установлена во что-то еще.useServerPrepStmts=false
и
определенные кодировки символов могут привести к повреждению, вставляя BLOB.
Как этого можно избежать?useServerPrepStmts
=
true
.SQL_MODE
=
NO_BACKSLASH_ESCAPES
.
Найди своих коллег! |
Вы можете направить письмо администратору этой странички, Алексею Паутову.