I have several datetime column in my MySQL DB. I want to trigger a java function when the date is reached. At worst, trigger a MySQL function can do the job as well. How to have a trigger datetime based on MySQL without doing cron job on every minute ?
Even a trigger wouldn't do the job, there must be a process to check (in your case if the date was reached)
Like Thomas said job or a task (CRON) that sets the trigger or an application to do what you wish with the database.
It is not ideal to do this in database, but if no better choice, you can achieve it by creating a MySQL event, which is a scheduled task.
You need to add a insert and/or update trigger to the database table and create the event based on the datetime value of the column
You can create the event in the way that drops itself after it is executed at the specified time.
Related
I am working on a spring boot project, the task is: I should lock editing capability of product for 15 minutes after creation, so basically if the user create a product, this product will be locked for editing for 15 minutes, after that it can be changed or deleted from the DB.
My question is: what is the best approach to achieve that:
1- Should I add a field to the DB table called lastUpdate and then check if the time of 15 minutes exceed.
2- Should I save all the newly created products in array and clear this array every 15 minutes.
or there is any better ways in regard to performance and best practice??
I am using springboot with JPA & mysql.
Thanks.
You should not use the locking available in InnoDB.
Instead, you should have some column in some table that controls the lock. It should probably be a TIMESTAMP so you can decide whether the 15 minutes has been used up.
If the 'expiration' and 'deletion' and triggered by some db action (attempt to use the item, etc), check it as part of that db action. The expiration check (and delete) should be part of the transaction that includes that action; this will use InnoDB locking, but only briefly.
If there is no such action, then use either a MySQL EVENT or an OS "cron job" to run around every few minutes to purge anything older than 15 minutes. (There will be a slight delay in purging, but that should not matter.
If you provide the possible SQL statements that might occur during the lifetime of the items, I may be able to be more specific.
you can make some check in your update method and delete method. If there are many methods, you can use AOP.
You can make use of both the functionalities you have mentioned.
First its good to have a lastUpdated field in tables which would help you in future also with other functionalities.
And then you can have an internal cache (map which has time and object reference), store objects in that and restrict editing for them. You can run a scheduler to check every minute and clear objects from you map and make them available for updating.
You could put your new products in an "incoming_products" table and put a timestamp column in that table that you set to date_add(now(), INTERVAL 15 MINUTE).
Then have a #Scheduled method in our Boot application run every minute to check if there are incoming products where the timestamp column is < now() and insert them as products and delete the corresponding incoming-products record.
I am using a RDBMS (mysql specifically), and I have a table that contains a date column.
What I would like to know is, how can I trigger an event to occur within my program (I am using Springboot, mysql, Apache Camel and Kafka together) when the date expires (i.e. a certain period of time has elapsed from the date).
Edit: for additional context, I am seeking to implement a reminder system that will fire when a certain time has passed
I implemented a solution by polling the database using camel's quartz2 component, running an sql query to check for entries with expired dates.
The query looks something like this, where you can alter INTERVAL for the amount of time before an entry is expired:
"SELECT entryID, submittedDate FROM db.tablename WHERE submittedDate + INTERVAL 7 DAY<= CURDATE()";
My camel route :
from("quartz2://YourGroup/YourDBpoller?cron=0+0/1+11-18+?+*+MON-FRI")
.to("bean:sqlBean?method=pollDB()").to("jdbc:datasource")
.convertBodyTo(String.class).process(new Processor() { ...})
Begins with the quartz2 component, which triggers periodically
Sends the sql query string (returned by the bean component)
Then handles the returned dataset (i.e. the expired entries) within the processor method.
In my case I only require the database to be polled once per day, however if real-time monitoring is required then this might not be appropriate.
There are few tables that quartz scheduler uses for scheduling jobs and to identify which job is running currently. It uses the following tables :
qrtz_fired_triggers
qrtz_simple_triggers
qrtz_simprop_triggers
qrtz_cron_triggers
qrtz_blob_triggers
qrtz_triggers
qrtz_job_details
qrtz_calendars
qrtz_paused_trigger_grps
qrtz_locks
qrtz_scheduler_state
So what is the purpose of each of these tables and what does it siginifies?
Thanks in advance.
I had the chance to work on quartz recently. I'm myself not 100% clear on this topic and I'm going to try my best to answer your question from my personal experience.
You must remember this basic flow-
1. Create a job.
2. Create a Trigger.
3. Scheduler(job, trigger)
All the above tables are based on the above 3 steps.
qrtz_triggers is where general information of a trigger is saved.
qrtz_simple_triggers, qrtz_simprop_triggers, qrtz_crons_triggers, qrtz_blob_triggers have a foreign key relation to qrtz_triggers which save those specific details. Ex. Cron has cron expression which is unique to it.
qrtz_job_details is simply the task to be executed.
qrtz_fired_triggers is a log of all the triggers that were fired.
qrtz_paused trigger is to save the information about triggers which are not active.
Calendars are useful for excluding blocks of time from the the trigger’s firing schedule. For instance, you could create a trigger that fires a job every weekday at 9:30 am, but then add a Calendar that excludes all of the business’s holidays. (taken from website. I havent' worked on it)
I honestly haven't worked in qrtz_locks, qrtz_scheduler_sate tables.
Check out this image which I reverse engineered using MySQL workbench.
I can provide some inputs for qrtz_lock and qrtz_scheduler_sate tables:
qrtz_lock stores the value of the instance name executing the job, to avoid the sceanario of multiple nodes executing the same job
qrtz_scheduler_state is for capturing the node state so that if in any case one node gets down or failed to execute one of the job then the other instance running in clustering mode can pick the misfired job.
Can anyone please suggest me the best approach for my requirement? I need to automatically update the table value after some specified time, using Java and MySQL as the database.
Using Quartz scheduler you can achieve this. You need to create one job and run that job at the required time so that it will fetch the data from the database and according to that you will do what's needed.
Quartz Scheduler Tutorial
Create a timer in Java.
Add a task to timer that updates value to MySQL.
Start timer
Example of Java Timer API: here
I am stuck at some point wherein I need to get database changes in a Java code. Request is to get any record updated, added, deleted in any table of db; should be recognized by Java program. How could it be implemented JMS? or a Java thread?
Update: Thanks guys for your support i am actually using Oracle as DB and Weblogic 10.3 workshop. Actually I want to get the updates from a table in which I have only read permission so guys what do you all suggest. I can't update the DB. Only thing I can do is just read the DB and if there is any change in the table I have to get the information/notification that certain data rows has been added/deleted or updated.
Unless the database can send a message to Java, you'll have to have a thread that polls.
A better, more efficient model would be one that fires events on changes. A database that has Java running inside (e.g., Oracle) could do it.
We do it by polling the DB using an EJB timer task. In essence, we have a status filed which we update when we have processed that row.
So the EJB timer thread calls a procedure that grabs rows which are flagged "un-treated".
Dirty, but also very simple and robust. Especially, after a crash or something, it can still pick up from where it crashed without too much complexity.
The disadvantage is the wasted load on the DB, and also response time will be limited (probably requires seconds).
We have accomplished this in our firm by adding triggers to database tables that call an executable to issue a Tib Rendezvous message, which is received by all interested Java applications.
However, the ideal way to do this IMHO is to be in complete control of all database writes at the application level, and to notify any interested parties at this point (via multi-cast, Tib, etc). In reality this isn't always possible where you have a number of disparate systems.
You're indeed dependent on whether the database in question supports it. You'll also need to take the overhead into account. Lot of inserts/updates also means a lot of notifications and your Java code has to handle them consistently, else it will bubble up.
If the datamodel allows it, just add an extra column which holds a timestamp which get updated on every insert/update. Most major DB's supports an auto-update of the column on every insert/update. I don't know which DB server you're using, so I'll give only a MySQL-targeted example:
CREATE TABLE mytable (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
somevalue VARCHAR(255) NOT NULL,
lastupdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX (lastupdate)
)
This way you don't need to worry about inserting/updating the lastupdate yourself. You can just do an INSERT INTO mytable (somevalue) VALUES (?) or UPDATE mytable SET somevalue = ? WHERE id = ? and the DB will do the magic.
After ensuring that the DB server's time and Java application's time are the same, you can just fire a background thread (using either Timer with TimerTask, or ScheduledExecutorService with Runnable or Callable) which does roughly this:
Date now = new Date();
statement = connection.prepareStatement("SELECT id FROM mytable WHERE lastupdate BETWEEN ? AND ?");
statement.setDate(1, this.lastTimeChecked);
statement.setDate(2, now);
resultSet = statement.executeQuery();
while (resultSet.next()) {
// Handle accordingly.
}
this.lastTimeChecked = now;
Update: as per the question update it turns out that you have no control over the DB. Well, then you don't have much good/efficient options. Either just refresh the entire list in Java memory with entire data from DB without checking/comparing for changes (probably the fastest way), or dynamically generate a SQL query based on the current data which excludes the current data from the results.
I assume that you're talking about a situation where anything can update a table. If for some reason you're instead talking about a situation where only the Java application will be updating the table that's different. If you're using Java only you can put this code in your DAO or EJB doing the update (it's much cleaner than using a trigger in this case).
An alternative way to do this is to funnel all database calls through a web service API, or perhaps a JMS API, which does the actual database calls. Processes could register there to get a notification of a database update.
We have a similar requirement. In our case we have a legacy system that we do not want to adversely impact performance on the existing transaction table.
Here's my proposal:
A new work table with pk to transaction and insert timestamp
A new audit table that has same columns as transaction table + audit columns
Trigger on transaction table to dump all insert/update/deletes to an audit table
Java process to poll the work table, join to the audit table, publish the event in question and delete from the work table.
Question is: What do you use for polling? Is quartz overkill? How can you scale back the polling frequency based on the current DB load?