«Не могу открыть больше таблиц» - лучшее сообщение об ошибке, чем «Не могу открыть больше баз данных», которое чаще встречается в моем опыте. Фактически, последнее сообщение почти всегда маскирует первое.
Механизм базы данных Jet 4 имеет ограничение в 2048 обработчиков таблиц . Мне не совсем понятно, является ли это одновременным или кумулятивным в течение жизни соединения. Я всегда предполагал, что это кумулятивно, поскольку на практике открытие меньшего числа наборов записей за один раз, кажется, позволяет избежать проблемы.
Проблема в том, что «дескрипторы таблиц» относятся не только к дескрипторам таблицы, но и к нечто гораздо большее.
Рассмотрим сохраненный QueryDef с этим SQL:
SELECT tblInventory.* From tblInventory;
Запуск этого QueryDef использует ДВА дескриптора таблиц.
Что ?, спросите вы? Он использует только одну таблицу! Но Jet использует дескриптор таблицы для таблицы и дескриптор таблицы для сохраненного QueryDef.
Таким образом, если у вас есть QueryDef вроде этого:
SELECT qryInventory.InventoryID, qryAuthor.AuthorName
FROM qryInventory JOIN qryAuthor ON qryInventory.AuthorID = qryAuthor.AuthorID
... если в каждом из ваших исходных запросов есть две таблицы, вы вы используете эти дескрипторы таблиц, по одному для каждого:
Table 1 in qryInventory
Table 2 in qryInventory
qryInventory
Table 1 in qryAuthor
Table 2 in qryAuthor
qryAuthor
the top-level QueryDef
Итак, вы можете подумать, что у вас задействовано только четыре таблицы (потому что есть только четыре базовых таблицы), но на самом деле вы будете использовать 7 дескрипторов таблиц ], чтобы использовать эти 4 базовые таблицы.
Если в наборе записей вы затем используете сохраненный QueryDef, который использует 7 дескрипторов таблиц, вы использовали еще один дескриптор таблицы, всего 8.
Назад в Jet 3.5 days исходное ограничение на обработку таблиц было 1024, и я столкнулся с ним в крайний срок, когда реплицировал файл данных после разработки рабочего приложения. Проблема заключалась в том, что некоторые из таблиц репликации открыты все время (возможно, для каждого набора записей?), И это использовало ровно столько дескрипторов таблиц, чтобы поместить приложение поверх.
В исходном дизайне этого приложения, Я открывал кучу тяжелых форм с множеством подчиненных форм, полей со списком и списков, и в то время я использовал много сохраненных QueryDefs для предварительной сборки стандартных наборов записей, которые я бы использовал во многих местах (точно так же, как вы бы с представлениями на любых серверная база данных). Проблема была устранена следующим образом:
загрузка подчиненных форм только тогда, когда они были отображены.
загрузка источников строк для полей со списком и списков только тогда, когда они были на экране.
удаление всех сохраненных QueryDef и использование операторов SQL которые присоединялись к необработанным таблицам, где это возможно.
Это позволило мне развернуть приложение в лондонском офисе всего на неделю позже запланированного срока. Когда вышел Jet SP2, он удвоил количество дескрипторов таблиц, что у нас все еще есть в Jet 4 (и, я полагаю, ACE).
С точки зрения использования Jet из Java через ODBC, ключевым моментом будет быть, я думаю:
используйте одно соединение во всем приложении, а не открывайте и закрывайте их по мере необходимости (что оставляет вас в опасности, что вы не сможете их закрыть).
открывайте наборы записей только тогда, когда они вам нужны, и очищайте и высвободите их ресурсы, когда закончите.
Теперь может быть утечка памяти где-то в цепочке JDBC => ODBC => Jet, где вы думаете , что высвобождаете ресурсы, а они не не выпускаются вообще. У меня нет конкретных советов по JDBC (поскольку я им не пользуюсь - я '
Есть вероятность, что у вас просто заканчиваются бесплатные сетевые подключения. У нас была эта проблема на загруженной системе на работе.
Следует отметить, что сетевые соединения, хотя и закрыты, могут не освободить сокет до времени сборки мусора. Вы можете проверить это с помощью NETSTAT / A / N / P TCP
. Если у вас много подключений в состоянии TIME_WAIT
, вы можете попробовать принудительно выполнить сборку мусора при закрытии подключения или, возможно, через определенные промежутки времени.
Вы также должны закрыть свой объект Connection.
Также было бы неплохо поискать альтернативу драйверу jdbc odbc. У меня нет опыта работы с альтернативой, но это было бы хорошим местом для начала:
Есть ли альтернатива использованию sun.jdbc.odbc.JdbcOdbcDriver?