SQLExecDirect doesn't return when deadlocked - c++

I have a C++ app calling a stored procedure via SQLExecDirect. If there is a deadlock SQLExecDirect doesn't return until the deadlock is resolved.
I've read in the .net world it can detect deadlocks and throw an exception. Is there any way with C++/ODBC to regain control while deadlocked? I suspect the answer is no, but I'm hoping there's some ODBC feature I haven't found yet.
The only work around I can think of is kicking off another thread to run it and and setting a timeout for the thread to return.
And no, I can't fix the deadlock. This app is running queries or stored procedures from my customer's DBs that they choose. I just don't want it unresponsive for the duration of the deadlock.

If your ODBC provider supports asynchronous execution you could perform the operation that way, ODBC 3.8+ even supports an event-based notification mode over the older 3.0 polling-only. Note that unless using something like SQLServer's MARS your connection will still be deadlocked it just allows the thread to do something else while waiting for an answer.

Related

Redisson: Why reactive client doesn't have PermitExpirableSemaphore?

I am using redisson reactive Java client. In non reactive client one could get an expirable Semaphore as:-
RPermitExpirableSemaphore semaphore = redisson.getPermitExpirableSemaphore("mySemaphore");
But If I create a reactive client, I can only find redisson.getSemaphore("value") function. I need PermitExpirableSemaphore because:-
I need a lock which could be released by different thread(so can't use RLock).
I need a lease timeout to prevent deadlock in case the lock aquiring thread is killed or stuck.
Is there any way to achieve this behavior in Redisson Distributed Locking?
Edit1: I can set lease time global in Config as:- Config().setLockWatchdogTimeout(leaseTimeMs), but I really need different leasetime at different locks.
Edit2: Asked a question on Redisson github at https://github.com/redisson/redisson/issues/1391
As linked in the edit2, there was no way of doing this in Redisson. Nikita, who is lead developer of Redisson quickly introduced the requested feature, to be launched in 2.11.6.

PostgreSQL: cancel query from C/C++ program

I'm using PostgreSQL 8.3, and writing a program in C++ that uses the libpq API. I execute commands asynchronously with the PQsendQuery() function. I'm trying to implement a timeout processing feature. I implemented it by calling PQcancel() when the timeout expires. I tested it with a query that returns 100 000 rows (it lasts about 0.5 s) with a timeout of 1 ms, and found that instead of cancelling the command, PQcancel() blocks until the server finishes execution, then returns with a successful query.
I understand that the documentation says that even with a successful cancel request the query may still be executed. My problem is that PQcancel() blocks my thread of execution, which is not acceptable because I use asynchronous processing (using the Boost Asio framework) so my program, which may have other tasks to do other than executing the SQL query, runs only on one thread.
Is it normal that PQcancel() blocks? Is there any way to make a non-blocking cancel request?
I looked at the implementation of PQcancel. It creates a separate TCP connection to the server, that's why it is blocking. This code part is exactly the same in the newest version of PostgreSQL too. So I concluded that there is no way to make it nonblocking other than starting the cancel in a separate thread. This is also the preferred way of using this feature, as the cancel object is completely independent from the connection object thus it is completely thread safe to use.
It sounds like you are doing this on a blocking connection. Check the documentation for PQsetnonblocking, set the connection to non-blocking and you should be able to get PQCancel to return immediately. But it will also make all operations on the connection non-blocking.

Does the sqlceclientsyncprovider provider lock the .sdf file during synchronisation on a mobile device?

I am using SQL Server Compact Edition 3.5 on a mobile device. Synchronisation using the sync framework works fine in the context of the user doing it via a button press and waiting for it to complete. There are no issues there.
I have recently attempted to do this in a background thread which runs every 'n' minutes or so. This also works fine, provided I am not using the database at the time. If I am using the database, the whole app locks up and I haven't yet found the specific exception that must be happening. I will continue to do that, but that is not part of my question.
My question is does the SqlCeClientSyncProvider somehow throw an exclusive lock or otherwise physically lock the .SDF file during synchronisation? If so, are there any options to override this behaviour?
No, it doesn't lock the .SDF file, after testing I see that at most it creates a transaction with a read committed isolation level. The issue I was having was a deadlocking issue in my own threading code -- which I was able to resolve after some careful refactoring. I was raising an event 'SyncBegun' before the sync happened and raising a subsequent event 'SyncEnded' afterwards. These were using separate locks which were stepping on each other's toes.

How to set a timeout for MySQL query using C API

I know there are lots of similar questions here, also there are lots of results, when I google it, but none of them answers my question. I read this, this, this and this but none of them works for me. I don't talk about any locks, I don't wanna do this using MySQL c++ connector, just the C API.
Also, what is very important here: I do this on LINUX. Why I mention this? Because in the documentation for mysql_options:
MYSQL_OPT_READ_TIMEOUT - ...This option works only for
TCP/IP connections and, prior to MySQL 5.0.25, only for Windows.
MYSQL_OPT_WRITE_TIMEOUT- ... This option works only for
TCP/IP connections and, prior to MySQL 5.0.25, only for Windows
So, is there any way to set a query timeout for versions, prior 5.0.25?
My MySQL version:
[root#xxx kiril]# mysql --version
mysql Ver 14.12 Distrib 5.0.22, for redhat-linux-gnu (i686) using readline 5.0
EDIT: At least, is there any way to cancel a query? I can start a timer as different thread, but when it expires.. can I cancel the query somehow?
Okay, I found a solution.. Thanks to Will and PRR( my co-worker ).
I cannot start a new thread on each query, as this is a real-time application, that is supposed to process 1000+ messages per second..(anyway, thanks to R.. for the idea).
Also, it was not possible to terminate the connection through the library, nor to cancel/kill the query, as the problem was in the DB server..
And here's a brute-force solution, but still much better that _EXIT( FAILURE ): Here's the related question: "How to force closing socket on Linux?" - so, I just closed the socket using a system call.
Important NOTE: (thanks Will) - It turned out, that our MySQL library wrapper has s "fail-safe" flag, so that on closed socket (or other critical error), it tries to "solve" the problem, so it reopens the socket, by itself, in my case. So, I just turned off this option and everything is fine now - the execute is terminated because of an exception - this is the "softest" way to do this.
This should be done through another thread, of course - a timer, for example.
EDIT: The timeouts are really working for versions after 5.0.25. But, at least on RHEL4 and RHEL5, the timeouts are tripled for some reason! For example, if some of the timeouts is set to 20sec, the real timeout is ~60sec..
Also, another important thing is, that these timeouts(as any other options) MUST be set after mysql_init and before mysql_connect or mysql_real_connect.
I suppose you could implement a timeout for the C function call (as described in this thread C++: How to implement a timeout for an arbitrary function call?), but you would need to think carefully about what kind of state you would leave the DB in - presumably these are just for reads of the database, not inserts/updates.
I have never tryed to do that, but i've been reading and i think that could means that MYSQL_OPT_WRITE_TIMEOUT and MYSQL_OPT_READ_TIMEOUT are only for windows prior MySQL version 5.0.25 but now sould be working for every TCP/IP connection. Take a look here
Regards
EDIT: I would try to update my mysql server to a newer version and try if it works.
If you don't mind using threads, you could start the query from a new thread and have the main thread perform a short pthread_cond_timedwait for the new thread to set a condition variable that it make the connection. Then you can let the thread linger around until the actual mysql call times out. Just make sure it's detached so its resources get freed when it finally does time out. This solution isn't pretty, but it should at least work.

How to timeout a mysql++ query in c++

I am using mysql++ in order to connect to a MySQL database to perform a bunch of data queries. Due to the fact that the tables I am reading from are constantly being written to, and that I need a consistent view of the data, I lock the tables first. However, MySQL has no concept of 'NOWAIT' in its lock query, thus if the tables are locked by something else that keeps them locked for a long time, my application sits there waiting. What I want it to do is to be able to return and say something like 'Lock could no be obtained' and try again in a few seconds. My general attempt at this timeout is below.
If I run this after locking the table on the database, I get the message that the timeout is hit, but I don't know how to then get the mysql_query line to terminate. I'd appreciate any help/ideas!
volatile sig_atomic_t success = 1;
void catch_alarm(int sig) {
cout << "Timeout reached" << endl;
success = 0;
signal(sig,catch_alarm);
}
// connect to db etc.
// *SNIP
signal (SIGALRM, catch_alarm);
alarm(2);
mysql_query(p_connection,"LOCK TABLES XYZ as write");
You can implement a "cancel-like" behavior this way:
You execute the query on a separate thread, that keeps running whether or not the timeout occurs. The timeout occurs on the main thread, and sets a variable to "1" marking that it occurred. Then you do whatever you want to do on your main thread.
The query thread, once the query completes, checks if the timeout has occurred. If it hasn't, it does the rest of the work it needs to do. If it HAS, it just unlocks the tables it just locked.
I know it sounds a bit wasteful, but the lock-unlock period should be basically instantaneous, and you get as close to the result you want as possible.
You could execute the blocking query in a different thread and never being bothered with the timeout. When some data arrives you notify the thread that needs to know about the status of the transaction.
If I was writing from scratch I would do that, but this is a server application that we are just doing an upgrade to rather than a large rework.
instead of trying to fake transactions with table locks, why not switch to innodb tables where you get actual transactions? just make sure to set the default transaction isolation level to REPEATABLE READ.
As I said, it is not so easy to 'switch' or re-architect when this is a live, in production system. I'm slightly frustrated that MySQL provides no methods to check for locks or choose not to hang waiting on a lock.
I don't know if this is a good idea in terms of resource usage and "best practices" and "cleanliness" and all the rest... but you have now repeatedly described the handcuffs that bind you in terms of re-architecting a "clean" system... so here goes.....
Could you open a new, separate connection just for sending the LOCK statement? Then close that connection when you catch the timeout alarm? By closing/destroying the connection that was dedicated to the LOCK statement, would not that essentially "cancel" the LOCK statment? I am not certain if such events would occur as I have described/guessed, but maybe it is something to test out.
My experience described so far indicates to me that closing a connection in which a query is running causes a seg fault. Therefore dispatching that query into a different connection wouldn't really help, as that would also seg fault.