powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / По одному соединению на поток или одно на все?
9 сообщений из 9, страница 1 из 1
По одному соединению на поток или одно на все?
    #39319059
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!

Помогите решить такую дилему: что лучше с точки зрения производительности - создавать на каждый поток (внутри потока) содинение с БД, использовать его и закрывать когда поток уничтожается или использовать одно соединение на все потоки - создавать при старте программы и затем просто предоставлять потокам?
Я пробовал оба варианта... и не выявил для себя абсолютных критериев, что правильно а главное надежно.
Замечу: приложение не очень сильно нагружено - порядка 200-300 клиентов (а значит и потоков) но критична именно скорость выполнения процедур на базе.

Также отдельное спасибо если будут советы по тюнингу оракла.

На данные момент работает один поток - одно соединение. Сервер иногда "вскипает" и в логах множество дедлоков. Так же непонятны причины почему иногда (при сильной нагрузке соединение рвется или процедуры выполняются некорректно)

Спасибо.

ЗЫ: .NET 4.5 C#
CONNECTION LIFETIME=0;DATA SOURCE=0.0.0.0:1521/orcl0;ENLIST=true;POOLING=true;INCR POOL SIZE=50;MAX POOL SIZE=2000;MIN POOL SIZE=100;PERSIST SECURITY INFO=True;STATEMENT CACHE PURGE=True;STATEMENT CACHE SIZE=2000;USER ID=??;Password=?????

Oracle.ManagedDataAccess 4.121.2.0
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319061
Фотография Павел Воронцов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunter,

Открой для себя такое понятие как "пул потоков". Книжки почитай, осознай почему именно такую архитектуру люди выбирают.

По тюнингу: большое количество дедлоков говорит о том, что вы не умеете обращаться с БД и даже не знаете что такое работа во многопотоковой конкуретной среде, зачем вообще СУБД нужна и как ее готовить. Без подробностей что же там ваша прикладуха пытается делать сказать ничего нельзя.
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319105
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Воронцов,

Сразу же видно, что Паша Воронцов - настоящий профессионал! Такие слова как "пул потоков", "почитай книжки" и прочие без сомнения выдают в нем высококвалифицированного специалиста. Жаль только, что он не умеет читать и с трудом понимает смысл заданного вопроса. Уверен, что его прикладухи рвут все рекорды производительности. Джон Скит консультируется с ним, а Маконелл подсматривал его исходники, восхищался и писал свою книгу.

Спасибо Паша!
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319107
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunterЖаль только, что он не умеет читать и с трудом понимает смысл заданного вопроса.

У вопроса так, как он задан, смысла нет вообще. Нечего понимать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319116
dmdmdm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunterТакие слова как "пул потоков", "почитай книжки" и прочие без сомнения выдают в нем высококвалифицированного специалиста.

Если выключить неуместную иронию, именно так.

Прежде чем "тюнинговать оракл", неплохо бы посмотреть, что делает приложение.
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319187
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отбросим тюнинг оракла нашим базаведам. Первый абзац поста. Что собственно из предложенных фраз не несет смысловой нагрузки?

Есть вообще смысл в том, что делает приложение? Вопрос звучит же совсем по-другому.

Но если это важно: оно принимает пакеты от клиентов, соединяется с БД (вот здесь см. первый абзац) - выполняет некие манипуляции с данными (вызывает хранимки) и возвращет клиенту ответ.

При соединении клиента с сервером (данное приложение) создается сеанс в контексте которого создается подключение к БД. Каждый сеанс работает в отдельном потоке. Соответственно при активных 20 клиентах - будет 20 соединений с БД.

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

Тут есть тонкость: вследствии того, что экземпляр класса-сеанса большой - он будет размещен в большой куче и после сборки мусора в куче останутся дырки (ибо она не подвержена дефрагментаации) и можно в итоге получить OutOfMemory.

Немного кода:
1. На один сеанс (поток) - одно подкючение к БД:
Код: c#
1.
2.
3.
4.
5.
public DbConnectionManager(ILogger logger)
        {
            Connection = new DbConnection(logger);
        }
        public DbConnection Connection { get; }



2. На все сеансы (потоки) - одно подкючение к БД:
Код: c#
1.
2.
3.
4.
public static class SharedConnectionManager
    {
        public static DbConnection Connection => DbConnection.Instance;
    }



Код: c#
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.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
public class DbConnection
    {
        private readonly OracleConnection _oracleDbConnection;
        private static DbConnection _appConnection;
        private string _lastMessage;
        private static ILogger Logger;

        internal DbConnection(ILogger logger)
        {
            Logger = logger;
            Logger.LoggerName = "OracleDbConnection";
            _oracleDbConnection = new OracleConnection(ConfigurationManager.ConnectionStrings["orclConnectionString"].ConnectionString);
        }

        internal static DbConnection Instance => _appConnection ?? (_appConnection = new DbConnection(Logger));

        public void Open()
        {
            _oracleDbConnection.Open();
        }

        public void Close()
        {
            _oracleDbConnection.Close();
        }

        public bool IsOpen()
        {
            return _oracleDbConnection != null && _oracleDbConnection.State == ConnectionState.Open;
        }

        public DbTransaction BeginTransaction()
        {
            return _oracleDbConnection.BeginTransaction();
        }

        public object ExecuteScalar(string commandString)
        {
            OracleCommand cmd = new OracleCommand(commandString, _oracleDbConnection);
            return cmd.ExecuteScalar();
        }

        public object ExecuteScalar(string commandString, DbTransaction transaction)
        {
            OracleCommand cmd = new OracleCommand(commandString, _oracleDbConnection)
            {
                Transaction = (OracleTransaction) transaction
            };
            return cmd.ExecuteScalar();
        }

        public OracleCommand ExecuteCommand(string procName, OperationCommands[] parameters)
        {
            var oracleCommand = new OracleCommand(procName, _oracleDbConnection)
            {
                CommandType = CommandType.StoredProcedure,
                AddToStatementCache = true
            };

            foreach (var command in parameters)
            {
                oracleCommand.Parameters.Add(command.OracleParameter);
            }

            oracleCommand.ExecuteNonQuery();
            return oracleCommand;
        }

        public OracleCommand ExecuteCommand(string procName, DbTransaction transaction, IEnumerable<OperationCommands> parameters)
        {
            var oracleCommand = new OracleCommand(procName, _oracleDbConnection)
            {
                CommandType = CommandType.StoredProcedure,
                AddToStatementCache = true,
                Transaction = (OracleTransaction)transaction
            };

            foreach (var command in parameters)
            {
                oracleCommand.Parameters.Add(command.OracleParameter);
            }

            oracleCommand.ExecuteNonQuery();
            return oracleCommand;
        }
    }



использование для варианта 1:
Код: c#
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.
public OracleDataBaseProvider(ILogger logger) // ctor для обработчика команд сеанса
        {
            _logger = logger;
            _logger.LoggerName = "OracleDataBaseProvider";
            _manager = new DbConnectionManager(_logger);
        }

private DbConnection Connection => _connection ?? (_connection = _manager.Connection);

private OracleCommand OracleCommand(OperationCommands[] parameters, string commandName, ref DbTransaction transaction)
        {
            try
            {
                if (!IsConnectionOpen) Connection.Open();
            }
            catch (Exception e)
            {
                _logger.Trace(() => GetTrace(e.Message));
            }

            transaction = Connection.BeginTransaction();
            var oracleCommand = Connection.ExecuteCommand(commandName, transaction, parameters.OrderBy(p => p.Position));

            transaction.Commit();
            transaction = null;
            return oracleCommand;
        }



OracleCommand - вызывается фабрикой, создающей команду (которая суть экземпляр класса созданный фабрикой) по запросу клиента. там все трай-кэтчи, создание парамтров и прочее..
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319188
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
... млин...

OracleCommand - вызывается экземпляром класса-команды созданным фабрикой по запросу клиента. там все трай-кэтчи, создание параметров и прочее..
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319199
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunterЧто собственно из предложенных фраз не несет смысловой нагрузки?

Слово "дилемма". Нет никакой дилеммы если ты знаешь хоть что-то о многопоточности и работе
коннекта. Если быть точным, то ты, как программист, должен понимать, что единый коннект
является глобальным ресурсом, доступ к которому нужно синхронизировать, чтобы не получить
кучу забавных глюков, вылазящих в непредсказуемых местах. И эта синхронизация производится
либо тобой самостоятельно, либо клиентской библиотекой Оракула автоматически (при указании
определённого флага). Ну а последствия сериализации обращений для твоего приложения никто
кроме тебя оценить не в силах.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
По одному соединению на поток или одно на все?
    #39319275
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Собственно при разделяемом коннекте и производится синхронизация с помощью критических секций.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / По одному соединению на поток или одно на все?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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