I'm developing WPF - EF Core desktop application for multiple users. I have to connect to a MySql server with a limited number of connections. Testing with a single desktop client i see my connections grows 3-4 instances so i'm worry worried about it.
I really dont understand why because my code only calls one instance at the same time.
How i could decrease these numbers?
May be MySql maintains a minimun opened connections pool ?
Can i force to EF Core to use only one instance for a desktop application instance?
Edit:
It's an Azure MySql database (limited opened connections per instance). I attach an active connections graph. First graphic's part (range values between 4-7) is when i'm using a single desktop user test, then i stop and connections come back to 4.
All my calls are synchronous and with this structure:
using(var context = database.getContext())
{
//Calls to database
db.Savechanges(); // if needed
}
Have you tried adding the pooling option to your connection string: pooling=false
var connectionString = "Server=server;Database=database;User ID=user;Password=pass;Pooling=false;";
Related
I am using aspnetboilerplate core and entityframework core.
I have 1 request entity framework core which is big:
var user = _userRepository.GetAll()
.Include(u => u.FavoriteMeals).ThenInclude(c => c.Category)
.Include(u => u.FavoriteRestaurants).ThenInclude(c => c.CategoryMaster)
.Include(u => u.FavoriteSpecialityMeals).ThenInclude(c => c.Speciality)
.Include(u => u.FavoriteSuperBookings).ThenInclude(c => c.Boooking)
.Include(u => u.FavouritePlaces).ThenInclude(c => c.Place)
.Include(u => u.Followers).ThenInclude(u => u.User1)
.Include(u => u.Followings).ThenInclude(u => u.User2)
.FirstOrDefault(r => r.Id == id);
I use AWS RDS MySQL. And I can see that the number of connections to the database is raising to 58 when I call the API through swagger.
Then I would like to know:
Is it normal to have arround 60 connections to the database? Then I plan to use this api connected to a mobile app.
The limit of max connections on aws is per mobile or global. I mean if two mobiles are connected to my api and calls the same api function are they gonna be blocked because the number of max connections was reached?
How can I optimize this?
Thanks,
///// EDIT
I have discovered that I have a lot of requests which are kept in slepp state.
How can I fix this? My code is a s below:
builder.UseMySql(connectionString);
//todo
builder.EnableSensitiveDataLogging(true);
builder.EnableDetailedErrors(true);
Please find below my requests result to find the sleep state
The reason many connections are open with a sleep status is, that by default, MySqlConnector which is used by Pomelo, has connection pooling enabled (Pooling=true), with a max. of 100 connections per connection string (MaxPoolSize=100). See MySQL .NET Connection String Options for all default settings.
So having around 60 connections opened can easily happen, when either 60 people use the app API in parallel, or e.g. when 3 different connection strings are used, each with 20 users in parallel.
Once those connections have been opened, they will effectively stay open for a long time by default.
With ConnectionLifeTime=0 as the default setting, they will never be explicitly closed by MySqlConnector's connection pooling management. However, they will always be closed after a number of seconds specified by the MySQL system variable wait_timeout. But since this variable is set to 28800 by default, it will take 8 hours before once created pooled connections are being closed by MySQL (independent of how long they were in a sleep state).
So, to lower the number of parallel connections, either disable Pooling (radical method with some performance implications if the server is not hosted locally) or manage their lifetime through the MaxPoolSize and ConnectionLifeTime connection string parameters.
In the screenshot you provided, you can see that the host varies in its address and port, but these are the address and outgoing port of the connecting client.
However, what I have written above does also apply here. So if you are connecting from multiple web servers (clients from the viewpoint of MySQL) to your database server, by default, each web server will manage its own connection pool and keep up to 100 connections open.
For example, if you have a load balancer setup, and multiple web servers behind it that may each execute database queries, or you run your API with some server-less technology like AWS Lambda, where your API might be hosted on many different web servers, then you might end up with multiple connection pools (one for each connection string on each web server).
My issue is that is only for one user connected. I am using Task.WhenAll() in my app which launches several api requests in parallel and I also use asynchronous methods in my api which creates some new threads.
If your client sends multiple web request (e.g. REST) to your API hosted on multiple web servers/AWS Lambda, then MySQL will at least need that many connections opened at the same time.
The MySqlConnector connection pooling will keep those connections open by default, after they were used (up until 100 connections per web server).
You will end up with the following number of sleeping database connections (assuming the connection string always stays the same on each web server):
number-of-parallel-requests-per-client * number-of-clients * number-of-webservers
However, the max. number of connections kept open will (by default) not be higher than:
number-of-webservers * 100
So if your app executes 20 requests in parallel, with each of them establishing a database connection from the API (web server) to the database server, then depending on your API hosting scenario, the following will happen:
3 Web Servers with Load Balancer: If you run your app often enough, the load balancer will distribute your requests to all 3 web servers over time. So each of the 3 web servers will keep around 20 connections open to your database server. You end up with 60 connections, as long as only one client executes these requests at the same time. If a max. of 4 clients run 20 requests in parallel, you will end up with 80 connections being kept open per web server over time, so a total of 3 * 80 = 240 total sleeping database connections.
Serverless technology like AWS Lambda: The same as in the previous example applies to AWS Lambda, but the number of web servers is infinite (in theory). So your might end up exceeding MySQL's max_connections setting pretty fast, if AWS decides to distribute the API calls to many different web servers.
Advice how to configure connection pooling
If you run your API on a fixed number of web servers, you might want to keep Pooling=true and set MaxPoolSize to a values, that number-of-parallel-requests-per-client * number-of-webservers will always be lower than max_connections, but if possible higher than typical-number-of-parallel-clients * number-of-parallel-requests-per-client. If that is not plausible or possible, consider setting Pooling=false or set MaxPoolSize to a number not higher than max_connections / number-of-webservers.
If you run your API on a serverless technology like AWS Lambda, either set Pooling=false or set MaxPoolSize to some low value and ConnectionLifeTime to some low value greater than zero. I would just set Pooling=false, because it is way easier to disable connection pooling than to effectively fine tune connection pooling for a serverless environment.
I'm using a multi-tenant architecture folowing the article Dynamic DataSource Routing, but creating new tenants (datasources) dynamically (on user registration).
Everything is running ok, but I'm worried with scalabillity. The app is read heavy and today we have 10 tenants but we will open the app to public and this number will increase a lot.
Each user datasource is created using the following code:
BasicDataSource ds = new org.apache.commons.dbcp.BasicDataSource();
ds.setDriverClassName(Driver.class.getName());
ds.setUsername(dsUser);
ds.setPassword(dsPassword);
ds.setPoolPreparedStatements(true);
ds.setMaxActive(5);
ds.setMaxIdle(2);
ds.setValidationQuery("SELECT 1+1");
ds.setTestOnBorrow(true);
It means it is creating at least 2 and a maximum of 5 connections per user.
How much connections and schemas does this architecture support by MySQL server (4 CPUs 2.3Mhz/8GB Ram/80GB SSD) and how can I improve it by changing datasource parameters or mysql configuration?
I know this answer depends of a lot of additional information, just ask in the comments.
In most cases you will not have more than 300 connections/second. That is if you add good caching mechanisms like memcached. if you are having more than 1000 connections/sec you should consider persistent connections and connection pools.
Our mysql hoster has a limit of concurrent db connections. As it is rather pricey to expand that limit the following question came up:
Info:
I have a web app (been developed by an external coder- in case you might wonder about this question).
The web app is distributed and installed on many servers (every user installs it on their pc). These satellites are sending data into a mysql db. Right now the satellites are posting into the db directly.To improve security and error handling i would like to have the satellites posting to a XML-rpc (wordpress api) which then further posts into the db.
Question:
would such api reduce number of concurrent connections or not?
(right now as every satellite connects directly. It is like 1 user = 1 connection)
If 10 satellites are posting to one file, this file then processes the data and posts them into the db -> has this been one connection? (or as many connections as different data sets have been processed.)
What if the api throttles a little bit, so as there is only posting at a time. Would this lead to just one connection or not?
Any pointers are well appreciated!
Thank you in advance!
If you want to improve concurrent connections to the database (because the fact is, creating a connection to the database is "expensive"). You should look into using a ConnectionPool (example with Java).
How are concurrent database connections counted?
(source: iforce.co.nz)
A connectionless server
Uses a connectionless IPC API (e.g., connectionless datagram socket)
Sessions with concurrent clients can be interleaved.
A connection-oriented server
Uses a connection-oriented IPC API (e.g. stream-mode socket )
Sessions with concurrent clients can only be sequential unless the server is threaded.
(Client-server distributed computing paradigm, N.A.)
Design and Performance Issues
Database connections can become a bottleneck. This can be addressed
by using connection pools.
Compiled SQL statements can be re-used by using PreparedStatements
instead of statements. These statements can be parameterized.
Connections are usually not created directly by the servlet but either
created using a factory (DataSource) or obtained from a naming service
(JNDI).
It is important to release connections (close them or return them to the
connection pool). This should be done in a finally clause (so that it is done
in any case). Note that close() also throws an exception!
try
{
Console.WriteLine("Executing the try statement.");
throw new NullReferenceException();
}
catch (NullReferenceException e)
{
Console.WriteLine("{0} Caught exception #1.", e);
}
catch
{
Console.WriteLine("Caught exception #2.");
}
finally
{
Console.WriteLine("Executing finally block.");
}
There are various problems when developing interfaces between OO and
RDBMS. This is called the “paradigm mismatch”. The main problem is that
databases use reference by value while OO languages use reference by
address. So-called middleware/ object persistency framework software
tries to ease this.
Dietrich, R. (2012). Web Application Architecture, Server Side Scripting Servlets. Palmerston North: Massey University.
It depends on the way you implement the centralized service.
If the service after receiving a request immediatly posts the data to mysql, you may have many connections if there are simultaneous requests. But using connection pooling you can control precisely how many open connections you will have. In the limit, you can have just one connection open. This might cause contention if there are many concurrent requests as each request has to wait for the connection to be released.
If the service receives requests, store them in some place (other then the database), and processes them in chunks, you can also have just one connection. But this case is more complex to implement because you have to control the access (reading and writing) to the temporary data buffer.
I'm using a MySQL instance on Azure under the free trial period. One thing I've noticed is that max_user_connections is set to 4 under this option and 40 under the highest priced tier.
Both of these seem really low, unless I'm misunderstanding something. Let's say I have 41 users making database requests simultaneously, wouldn't this cause a failure due to going over the max allowable connections? That doesn't seem like much room.
How can I use Azure to allow a realistic number of simultaneous connections? Or am I thinking about this incorrectly? Should I just dump MySQL for SQL Azure?
Thanks.
If you are using the .NET framework, connection pooling is managed by the data provider. Instead of opening a connection and leaving it open for an entire session, with .NET each database operation/transaction typically opens the connection, performs a single task and then closes the connection after the operation completes. The .NET MySQL data provider also supports advanced connection pooling, see http://www.devart.com/dotconnect/mysql/docs/ComparingProviders.html
I would assume the Azure limitation is referring to applications that employ the first (session duration) alternative.
I've been thinking, why does Apache start a new connection to the MySQL server for each page request? Why doesn't it just keep ONE connection open at all times and send all sql queries through that one connection (obviously with client id attached to each req)?
It cuts down on the handshake time overhead, and a couple of other advantages that I see.
It's like plugging in a computer every time you want to use it. Why go to the outlet each time when you can just leave it plugged in?
MySQL does not support multiple sessions over a single connection.
Oracle, for instance, allows this, and you can setup Apache to mutliplex several logical sessions over a single TCP connection.
This is limitation of MySQL, not Apache or script languages.
There are modules that can do session pooling:
Precreate a number of connections
Pick a free connection on demand
Create additional connections if not free connection is available.
the reason is: it's simpler.
to re-use connections, you have to invent and implement connection pooling. this adds another almost-layer of code that has to be developed, maintained, etc.
plus pooled connections invite a whole other class of bugs that you have to watch out for while developing your application. for example, if you define a user variable but the next user of that connection goes down a code path that branches based on the existence of that variable or not then that user runs the wrong code. other problems include: temporary tables, transaction deadlocks, session variables, etc. all of these become very hard to duplicate because it depends on the subsequent actions of two different users that appear to have no ties to each other.
besides, the connection overhead on a mysql connection is tiny. in my experience, connection pooling does increase the number of users a server can support by very much.
Because that's the purpose of the mod_dbd module.