I have a interface where users can select a stored proc and pass parameters to the stored proc.
Based on what the user selects, the query can run for a long time.
If the query takes more than 5 minutes I want to stop the query and send an email to the user asking him to contact the developer.
Basically how do we pass a time out parameter to query?
It is not possible to do it in the same SQL stored procedure, because this is a sequential execution, and there is not any possibility to fork a connexion or perform a parallel execution.
You can eventually create a external stored procedure in Java or C, that will create a thread for monitoring purposes and then trigger the finalisation of the job if it is getting too much time.
Also, you can create an infinitive loop in a SP that will be activated each minute to check the processes, and kill the ones that have taken more than a certain quantity of time, but this is NOT recommended.
You can use the built-in module UTL_MAIL to send an email and terminate a process via admin_cmd but you have to create a monitoring process in parallel, and that is not possible from the same connexion.
You can check a Serge Rielau's article in his blog that could give you many ideas: https://www.ibm.com/developerworks/community/blogs/SQLTips4DB2LUW/entry/sleep?lang=en
Query timeout is a client configuration parameter, set via db2cli.ini, db2dsdriver.cfg, or the JDBC connection property, depending on the client version and type. To enforce query run time limit on the server side, where the stored procedure runs, you will need to use Workload Manager.
In either case I don't think you'll be able to trigger an email notification to the client.
Related
I have a web application that sends an email on certain action. So, for that, it saves the request in database, and then one email worker thread picks up the request and sends the email. Email worker watches the database for changes.
Now I want to have the same web application running behind load balancer sharing the same database. Now the problem is when I'll create an email request in database, there is a possibility that the email worker running inside the similar web application on different machine behind load balancer might see the database entry of email at the same time and this will result in same email being sent multiple times.
So, Is there any way to prevent this situation other than explicitly locking a table?
I've read this question Distributing java threads over multiple servers?
but don't know whether the solutions provided there will suffice my need. Terracotta seems to be the solution, but I think it will need explicit synchronization to be added to the code, don't know.
Any knowledge on this will be helpful.
A simple, low-tech solution would be to have the email sending worker running just once.
This can be achieved either by extracting the worker to a separate application, which is triggered for example by cron, or by making it configurable, whether an instance of your web application has the email worker activated. In the latter case it is up to you to make sure that only one of the load balanced instances has the email worker active
The downside would be that E-Mail sending would not be redundant, i.e. if the host on which email sending is active is down, no one is sending any emails.
If you need redundancy you'd have to rely on some distributed middleware, as in the question you linked above, or implement a synchronization mechanism yourself.
For an own implementation you could look at optimistic locking using a version number field/column on the email request, as supported by Hibernate/JPA (see https://stackoverflow.com/a/19456821/981913). The algorithm would be something along the following lines:
Worker wakes up, finds email request in the DB, and version column = 0
Worker updates the request with version = 1. Update only succeeds if version was 0 before, meaning no other worker updated it to 1
since the request was read at step 1.
if update from step 2 was successful, worker can safely assume no other worker will process this reques, and go ahead and send the email
Use SQL transactions to lock a row for processing.
Your email row should have 2 columns added, TIMESTAMP type: processed_time, send_time but default to NULL
Begin transaction
select 1 item where processed_time is NULL and send_time is NULL and use highest level of serialization for that database (see something like In SQL Server, how can I lock a single row in a way similar to Oracle's "SELECT FOR UPDATE WAIT"?), every DB/ORM has a way of doing this, postres uses SELECT FOR UPDATE, etc.
update row and set processed_time to NOW()
commit (but don't close transaction, if email fails you may need to handle that or rollback
4a. At this point you have claimed that row for yourself so another thread would not get that row at step 2 and needs to be done asap
send email
update row and set send_time to NOW()
End transaction
You may need to fine tune this process based on DB/ORM you are using but the general idea holds.
I've a typical scenario & need to understand best possible way to handle this, so here it goes -
I'm developing a solution that will retrieve data from a remote SOAP based web service & will then push this data to an Oracle database on network.
Also, this will be a scheduled task that will execute every 15 minutes.
I've event queues on remote service that contains the INSERT/UPDATE/DELETE operations that have been done since last retrieval, & once I retrieve the events for last 15 minutes, it again add events for next retrieval.
Now, its just pushing data to Oracle so all my interactions are INSERT & UPDATE statements.
There are around 60 tables on Oracle with some of them having 100+ columns. Moreover, for every 15 minutes cycle there would be around 60-70 Inserts, 100+ Updates & 10-20 Deletes.
This will be an executable jar file that will terminate after operation & will again start on next 15 minutes cycle.
So, I need to understand how should I handle WRITE operations (best practices) to improve performance for this application as whole ?
Current Test Code (on every cycle) -
Connects to remote service to get events.
Creates a connection with DB (single connection object).
Identifies the type of operation (INSERT/UPDATE/DELETE) & table on which it is done.
After above, calls the respective method based on type of operation & table.
Uses Preparedstatement with positional parameters, & retrieves each column value from remote service & assigns that to statement parameters.
Commits the statement & returns to get event class to process next event.
Above is repeated till all the retrieved events are processed after which program closes & then starts on next cycle & everything repeats again.
Thanks for help !
If you are inserting or updating one row at a time,You can consider executing a batch Insert or a batch Update. It has been proven that if you are attempting to update or insert rows after a certain quantity, you get much better performance.
The number of DB operations you are talking about (200 every 15 minutes) is tiny and will be easy to finish in less than 15 minutes. Some concrete suggestions:
You should profile your application to understand where it is spending its time. If you don't do this, then you don't know what to optimize next and you don't know if something you did helped or hurt.
If possible, try to get all of the events in one round-trip to the remote server.
You should reuse the connection to the remote service (probably by using a library that supports connection persistence and reuse).
You should reuse the DB connections by using a connection pooling library rather than creating a new connection for each insert/update/delete. Believe it or not, creating the connection probably takes 100+ times as long as doing your DB operation once you have the connection in hand.
You should consider doing multiple (or all) of the database operations in the same transaction rather than creating a new transaction for each row that is changed. However, you should carefully consider your failure modes such that you don't lose any events (if that is an important consideration).
You should consider utilizing prepared statement caching. This may help, but maybe not if Oracle is configured properly.
You should consider trying to analyze your operations to find any that can be batched together. This can be a lot faster if you have some "hot" operations that get done often.
"I've a typical scenario"
No you haven't. You have a bespoke architecture, with a unique data model, unique data and unique business requirements. That's not a bad thing, it's the state of pretty much every computer system that's not been bought off-the-shelf (and even some of them).
So, it's an experiment and you must approach it as such. There is no "best practice". Try various things and see what works best.
"need to understand best possible way to handle this"
You will improve your chances of success enormously by hiring somebody who understands Oracle databases.
I am using Informix DB. This question may not be tied to one specific database. But I want to know how I can in Java, continuously probe into a Database and check if a certain row has been added to a table in the DB. Basically, the flow is:
My Java application should use JDBC to check if a certain table is populated.
If no, it should wait until a row has been inserted.
My question how can I have Java be aware of a row insertion. I am not expecting to add any triggers or anything, but in pure Java be able to check that the row is added.
Some thoughts that come to my mind are continuously call DB for the row, or periodically (every half-hour or so) call DB and check if the row is available. But what I am looking for is something like a Listener which can do this.
There is no facility in the Informix DBMS to signal when a particular row arrives in a table.
Well, I say that, but there is the DB-Cron facility which can periodically execute tasks (inside the server), and you could conceivably schedule a task to poll for the data to see if it has arrived and to send a message (somehow) to indicate that it has. It would be non-trivial, especially the part the indicates that it has arrived.
The JDBC protocol (and SQL protocols generally) are essentially synchronous; the client sends a request and waits for an answer from the DBMS.
So, pragmatically, if your delay period is half an hour, you can either create an admin task to handle the processing (you could write a Java UDR to be executed in the server by the server if that's crucial to you), or you can arrange for the Java (client-side) program to poll periodically to find out whether the information you need is there. A half-hour delay is not going to stress anything, even with a moderate number of processes polling for separate values (or even the same value). On the other hand, you normally try to avoid polling when you can. You'll need to strike a balance between responsiveness to the special data arriving and general system responsiveness. On the whole, general system responsiveness is more important, so keep the polling interval as large as you can.
If your polling interval needed to be sub-second, then the balance would be different - the job would be a lot harder.
Scenario:
There's a task-manager application that allows its users to create tasks and associate a timestamp with it.
Goal:
The application is supposed to send email alerts to the users at the time when any of their tasks are due.
Question:
If there's a function in the application sendEmailAlerts, which queries database, fetches all those tasks which are due now, and send their creators alerts; is it possible to trigger this function exactly at the moment when a task is due?
The approach that I have in mind is to use a Quartz job, that would run every x minutes and invoke sendEmailAlerts. But this approach doesn't seem very efficient. Is there any better way of doing it?
Thank you for your help.
You could use SQL Server Agent to create a job to execute at a specified time, although in this scenario i don't think it's optimal to create x jobs for x alerts.
I have a Java servlet that runs a database query that may take several minutes to run before attempting to write to the response stream. During the database query the user may have disconnected (thus making the query useless).
Since I can't kill it in the database thread, I'm trying to kill it from another thread. Do any of the servlet containers provide a recommended way of "canceling" or "killing" a request thread? If I carry a reference to the Thread around, can I force an interrupt or similar?
Tour question is not about java threads. It is about killing database query into the database. I say it because as far as I understand your question what happens is that client sends HTTP request to servlet that performs JDBC connection and runs query that takes a lot of time. So, java does not work this time. The DB does. This means that you have to kill the DB query into the DB. How to do this? This depends on your database. MySql (for example) has a kind of command line shell that allows retrieving the list of current queries and terminating the queries. So this is what you can do. Your second servelet may connect to MySql, retrieve running queries, identify which one should be killed (this is application specific functionality) and kill it. I believe that once you do this the first servlet will get JDBCException and can exit.
This is the way to show list of running queries:
http://www.electrictoolbox.com/show-running-queries-mysql/
Here is how to kill query:
http://dev.mysql.com/doc/refman/5.0/en/kill.html
And the last note that probably should be the first. Check why is your query taking so long time? IMHO in most cases it means that your schema is not optimal or some index is missing. Generally, if your query takes more than 0.1 seconds check your DB schema.
If you are running a hour long DB query , you should not in first
place call from a servlet ,as you response stream will timeout, you will
get 504.
May i know what this query is doing, something involving
calculation and large updates or
inserts.
you should try placing this query in DB JOBS.
You can java.sql.Statement.cancel() you will have to have the running statements registered somewhere (ServletContext or whatever structure you find fit) and unregistered upon completion.
The JDBC driver must support this method (cancel()) as well, I don't know if PostgreSQL supports it, though