How to simulate "Mysql2::Error: MySQL client is not connected" - ruby-on-rails

Can anyone suggest a way of forcing the above exception to occur, in the context of a Rails app?
I have a particular situation where it arises (involving scheduled database maintenance) and I need to be able to trigger it locally so I can test my application handles it correctly.
I would guess there's either something I could do to the DB itself, or else some method I could call on the ActiveRecord connection that would trigger this, but I haven't been able to figure it out.

You are probably getting this error because the MySQL connection is killed during maintenance while a SQL query is being made. (Here is a test case of this scenario https://github.com/brianmario/mysql2/blob/a8c96fbe277723e53985983415f9875e759e1d47/spec/mysql2/client_spec.rb#L597)
To reproduce this locally, you can run a long running SQL query in rails. E.g.
ActiveRecord::Base.connection.execute("select sleep(100)")
While that is running, find and kill the rails SQL connections by running
SELECT id FROM INFORMATION_SCHEMA.PROCESSLIST WHERE `db` = '<your-database-name>';
kill <id>; -- Run for each id listed in the previous query.

Find connection ID
ActiveRecord::Base.connection.raw_connection.thread_id
# or
ActiveRecord::Base.connection_pool.connections.map { |conn| conn.raw_connection.thread_id }
or by SQL like mentioned in Cameron's answer
By mysql client invoke
KILL <ID>; -- which you have got by #thread_id
Future attempts to query via this connection will fail with "Mysql2::Error: MySQL client is not connected"
Notes:
Option reconnect: true in database.yml will lead to immediate reconnect after a KILL. You able observe it by calling #thread_id again, it will return new ID.
ActiveRecord::Base.connection uses separate connection for thread where it have been called. While we have killed single connection, another threads will be able to query mysql without error.
You able to access all process connections by
ActiveRecord::Base.connection_pool.connections
You may wonder why in console for pool size, for say, 5 (ActiveRecord::Base.connection_pool.size) you have got ActiveRecord::Base.connection_pool.connections.count == 1. In this case you may checkout more connections by
ActiveRecord::Base.connection_pool.checkout

Related

Gracefully force database reconnection in Rails 4

We have a Rails 4 app that uses a database that sometimes gets updated by having a new instance of the database spun up and then ops updates the DNS record to point to the new instance (not ideal, but I can't change that). The problem is that the Rails connection pool still keeps its connections open to the old database and won't talk to the new database unless we restart Rails. We can do that, but it's a pain.
We would like to have an administrative endpoint we could hit that tells the app to gracefully close database connections and restart. ActiveRecord::Base.connection_pool.disconnect! certainly closes the old database connections and when new ones are requested, they talk to the new instance, but it also takes a shotgun to any running queries and terminates them rather than letting them finish.
Is there a way to tell Rails to refresh all of its database connections at runtime in a way that will allow currently running queries to finish before being closed?

SQL Server connection established during design, but not during runtime

I have created an Amazon RDS DB instance. I can connect to it and perform operations with SSMS. I can also bind to it using Entity Framework DB-first and generate my model. However, when I run my app, using the same connection string that was generated in the data access project, I get a "the network path was not found" error while trying to establish a connection to the DB.
Let me be clear: the db exists, the right ports are open, and the connection string is correct. I am the only one connecting to the database and the status is "available".
So what's going on? Has anyone experienced something like this?
Let me also further mention that I have already checked the usual things like internet connectivity, firewall rules, state of the database, etc.
well it started working all of a sudden. So I guess this problem will only pop up again in production or something.

Dealing with service dependencies that time out or fail

I have writen a windows service that overwrite Logon and Logoff methods of ISenesLogon2 to check out when logon and logoff occure and then insert the log information into the sql server on server computer.
But it has problem when i turn on the client computer just after the server.
In this situation my service could not insert in sql server.
I think it's because of that the sql server did not load completely before the winservice tried to access to it.
So i want to find a way to check programmatically if the sql server is ready and then try to work with?
Your service cant start until its dependencies remote or otherwise have also started. Checking SQL Server is easy, try and connect to it and retry until you succeed.
Only problem is services have timeouts on startup, you cant sit and repeat this indefinitely.
Things that cannot be reliably started in a reasonable timeframe should not be services or they should fail as soon as possible. Otherwise you will end up with a lot of support requests for your service timing out.
Services are also usually not interactive to the user, so the failure is worse because you cant directly tell the user that your not up unless you do a tray icon.

Oracle ODP.Net and connection pooling

this is really two questions in one I guess.
We've developed a .Net app that accesses an Oracle database, and have noticed that after changing the user's Oracle password, the app continues to work for a short time with the old password in the connection string. Presumably this is something to do with the way existing connections are pooled?
When first investigating this we tried turning off pooling in the connection string, however the app wouldn't work, throwing the error "Unable to enlist in a distributed transaction" at the point it tries to open a connection. While we probably wouldn't want to turn off connection pooling in a production app, I'm curious as to why MSDTC seems to need it?
We are using Oracle 11g (11.1.2) and latest ODP.Net (11.2 I think).
Thanks in advance
Andy
Please see some of the finding below:
For Question One: (application still connected with old DB password)
If we connect the database with connection pooling option, connection pool manager would create and maintain the number of connection sessions when first calling the open or close of OracleConnection object. (number of this connection sessions depend on "min" & "max" pool size in connection string). In Oracle, I think you could check active session like:
SELECT s.inst_id,
s.sid,
s.serial#,
p.spid,
s.username,
s.program
FROM gv$session s
JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id
WHERE s.type != 'BACKGROUND';
And according to Oracle doc, this connection pooling service will close the connection sessions after 3 minutes of in-active state. [ http://docs.oracle.com/html/E10927_01/featConnecting.htm ]
So the most possible reason could be, your application still
connected to the database by using this Pool and still connected for
a short time, even after you changed the database password.
There could be also one possibility of "Oracle Client Cache"
feature in ODP.net. But not quite sure, you can check at, [
http://www.oracle.com/technetwork/issue-archive/2008/08-jul/o48odpnet-098170.html ]
For Question Two: (why MSDTC needed)
If you are using nested Database connection in your code, it will be promoted to DTC. [ http://petermeinl.wordpress.com/2011/03/13/avoiding-unwanted-escalation-to-distributed-transactions/ ] Actually there was Oracle Service for Microsoft Transaction Server (OraMTS) act as among ODP.net, DTC, and Oracle Database.
But you didn't happend this problem (MSDTC) before disabled the connection pooling. It seems like your code is reusing the same connection out of undelining connection pool, and it might eliminate the need to promote DTC. There was similar question on StaffOverflow. [ Why isn't my transaction escalating to DTC? ]

How Rails handles database connection in the background?

I am trying show controller specific pages in my rails app when the database connection goes away. I do this by catching the Mysql::Error in the rescue_action method and rendering appropriate pages. When the mysql service alone is stopped , i get the Mysql::Error exception really quickly and i could render the pages without any delay.
But when the server itself is shut down, rails takes 3 mins to throw the Mysql::Error and after 5-6 request the whole website becomes unresponsive.
I tried to figure out, which method in rails framework takes such a long time , when the mysql server is shut down. It was a method connection.real_connect (in the active record mysql_adapter file),which took 3 mins to return with an exception.
so i decided to timeout out this method using systemTimer gem. This monkey patch worked perfectly, when i start the website with database connection and immediately shutdown the database server.
But when i start the website with database, and access the website for sometime and then shut down the database server, it doest work at all. and the whole website becomes unresponsive as before. I wonder what is the difference between the two scenarios.
I think i need to know more in detail about how rails handle database connection . how it reacts when the database connection goes off. so that i could identify exact places where i can put monkey patches and make it work for my spefic requirement. I havent seen any relevant article explaining this.
Any help will be very useful for me
Thanks,
I've not tried this, but you can add connect_timeout as one of the specified options (along with port, host, etc) for the MySQL connection in the database.yml file. That value is passed to the real_connect call to establish the connection to MySQL.
Furthermore, since you are experiencing a delay after the initial connection is made and the DB is shutdown, you may need to use the read_timeout config option.

Resources