processBuilder failing to load data on different host? - java

On host 'A' I start a transaction by inserting values to a table in DB. As soon as I insert, I call processBuilder to refresh host 'B' which in-turn should load the updated values from same DB table to cache. But the values are not getting loaded.
Is there any relation between processBuilder and transaction? Because the transaction is yet to complete on the host from where I am calling processBuilder.
I tried fetching values from DB before calling processBuilder on host 'A' and it is returning the values which was recently inserted (result set returns 10 rows) where as on host 'B' which is calling same select statement return 9 rows.

"as soon as I insert" red flag.
Yes, there is a relationship between the transaction and processBuilder. If the transaction is not committed, then all other sessions will not be able to see the changes. If you're used to programming in a DB app environment where autocommit is enabled and switch to a DB app environment where autocommit is disabled, then you are likely to run across this kind of problem.

Related

Auto attached records get detached after commit

I have want to fetch a list of Relation records, and I'll use .fetchInto(RELATION); and I want to iterate over the list and commit each iteration to the database. This doesn't seem to be working for me because I get Caused by: java.sql.SQLException: Connection is closed while updating the record. I don't have this problem with regular jOOQ queries. And it doesn't seem any connections are closed.
When I use contact.attach(jooq().configuration()) it seems to be working again. How can I prevent it from detaching?
I start and commit a transaction through JPA.em().getTransaction().*.
org.jooq.exception.DataAccessException: SQL [update `Relation` set `Relation`.`organizationName` = ? where `Relation`.`id` = ?]; Connection is closed
at org.jooq_3.15.1.MYSQL.debug(Unknown Source)
at org.jooq.impl.Tools.translate(Tools.java:2979)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:643)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:349)
at org.jooq.impl.UpdatableRecordImpl.storeMergeOrUpdate0(UpdatableRecordImpl.java:331)
at org.jooq.impl.UpdatableRecordImpl.storeUpdate0(UpdatableRecordImpl.java:228)
at org.jooq.impl.UpdatableRecordImpl.lambda$storeUpdate$1(UpdatableRecordImpl.java:220)
at org.jooq.impl.RecordDelegate.operate(RecordDelegate.java:143)
at org.jooq.impl.UpdatableRecordImpl.storeUpdate(UpdatableRecordImpl.java:219)
at org.jooq.impl.UpdatableRecordImpl.update(UpdatableRecordImpl.java:156)
at org.jooq.impl.UpdatableRecordImpl.update(UpdatableRecordImpl.java:151)
at worker.taskprocessors.BulkContactEditWorker.execute(BulkContactEditWorker.java:144)
Example:
var contacts = jooq()
.selectFrom(
RELATION
.join(BULK_CONTACT_EDIT_CONTACTS)
.on(
BULK_CONTACT_EDIT_CONTACTS
.CONTACT_ID
.eq(RELATION.ID)
.and(BULK_CONTACT_EDIT_CONTACTS.BULK_CONTACT_EDIT_ID.eq(bulkContactEditId))
.and(BULK_CONTACT_EDIT_CONTACTS.PROCESSED.isFalse())))
.limit(batchSize)
.fetchInto(RELATION);
if (!JPA.em().getTransaction().isActive()) {
JPA.em().getTransaction().begin();
}
for (RelationRecord contact : contacts) {
contact.attach(jooq().configuration()); // I have to add this line to make it work.
contact.setOrganizationName("OrganizationName");
contact.update();
JPA.em().getTransaction().commit();
if (!JPA.em().getTransaction().isActive()) {
JPA.em().getTransaction().begin();
}
}
What's the problem
You're fetching your jOOQ RelationRecord values outside of a JPA transactional context, so that fetching runs in its own transaction (this is independent of jOOQ). jOOQ will always try to acquire() and release() a connection for every query, and when that happens outside of a transactional context, then the connection will be effectively closed (e.g. returned to the connection pool). You should switch the order of starting a transaction and running the jOOQ query:
// start transaction
// run jOOQ query
// iterate jOOQ results
// run updates
// commit transaction
If you're using declarative transactions (e.g. Spring's #Transactional annotation), then you're less likely to run into this problem as your initial jOOQ query will more likely also be in the same transaction already.
Why did attaching work
When you explicitly attach the RelationRecord to the configuration, then you will attach a record that has been attached to the previously closed connection to the new configuration with the transactional connection. I'm assuming that your jooq() method produces a new DSLContext instance, which wraps the currently active DataSource or Connection.
Switch to bulk updates
However, if your example is all there is to your actual logic (i.e. you haven't simplified it for this Stack Overflow question), then why not just run a bulk update? It will be simpler and much faster.
jooq()
.update(RELATION)
.set(RELATION.ORGANIZATION_NAME, "OrganizationName")
.where(RELATION.ID.in(
select(BULK_CONTACT_EDIT_CONTACTS.CONTACT_ID)
.from(BULK_CONTACT_EDIT_CONTACTS)
.where(BULK_CONTACT_EDIT_CONTACTS.BULK_CONTACT_EDIT_ID.eq(bulkContactEditId))
.and(BULK_CONTACT_EDIT_CONTACTS.PROCESSED.isFalse())
))
// Since you're using MySQL, you have native UPDATE .. LIMIT support
.limit(batchSize)
.execute();
I'm assuming your actual example is a bit more complex, because you need to set the PROCESSED flag to true somewhere, too, but it's always good to keep this option in mind.

Stop, restore and restart MS SQL server

I have a build deployed on my local and I am able to access the application using https://localhost:8443/dashboard. Now, as a part of my junits, I am supposed to take the backup of the database used by this application and restore it to its earlier state as the application inserts some data across multiple tables as a part of the tests. So, I need to restore the DB before the tests run. Now, I am able to backup and restore it using java program (junit) but the problem is coming when the server is running. It says DB is already in use and can't restore. Is there a way to disconnect the db connection (user) used in the application, do the restoration and then connect back again so that I don't have to shutdown the server and start it manually again.
Using commands similar to following -
BACKUP DATABASE [Store] TO DISK = N'"+backuppath+"' WITH NOFORMAT, NOINIT,
NAME = 'demodb-full', SKIP, NOREWIND, NOUNLOAD, STATS = 10";
And
RESTORE DATABASE ["+dbName+"] FROM DISK='"+database_backup_location+"' WITH
REPLACE, MOVE '"+mdfLogicalName+"' TO
'"+getPropertyByKey("databse.dbfiles.location")+mdfLogicalName+".mdf', MOVE
'"+ldfLogicalName+"' TO
'"+getPropertyByKey("databse.dbfiles.location")+ldfLogicalName+".ldf';
Error that I am getting -
org.springframework.jdbc.UncategorizedSQLException: StatementCallback;
uncategorized SQLException for SQL [RESTORE DATABASE ....error code [3101];
Exclusive access could not be obtained because the database is in use.; nested
exception is com.microsoft.sqlserver.jdbc.SQLServerException: Exclusive access
could not be obtained because the database is in use.
I am already using the BACKUP and RESTORE commands. RESTORE command
gives error because the database is in use.
I've already answered, you just need to set your database offline this way:
alter database myDB set offline with rollback immediate
Doing this you'll disconnect all the users from your db and now you can make a RESTORE
You need to do below steps :
Backup the database
BACKUP DATABASE [Store] TO DISK = N'"+backuppath+"' WITH NOFORMAT, NOINIT,
NAME = 'demodb-full', SKIP, NOREWIND, NOUNLOAD, STATS = 10";
Kill existing connections
USE master;
DECLARE #kill varchar(8000); SET #kill = '';
SELECT #kill = #kill + 'kill ' + CONVERT(varchar(5), spid) + ';'
FROM master..sysprocesses
WHERE dbid = db_id('Store')
EXEC(#kill);
Then run the restore script.

Locked entities in postgres after retrieval

We have a table in postgres that we use for our system configurations, from which i want to delete configurations with certain ids. The problem is that just before the deletion, we have some code that fetches some of the configuration entries and on the next step (the deletion one) i can't delete them because the rows are locked. I've checked the pg_locks table and each configuration retrieval's transaction stays in postgres for around a minute. And it stays in status "idle in transaction", while the deletion step is waiting on it.
This is how we retrieve the configuration entities
Query query = getEntityManager().createQuery("some query");
...
list = query.getResultList();
There's no transaction involved, we don't really add any transactional jta, ejb annotations, i guess it's added automatically and after this query is where it gets locked.
And this is how we try to delete the rows
Query query = getEntityManager().createNamedQuery(namedQuery);
query.executeUpdate();
Thats it. Nothing special, yet since some rows are locked, the query fails on waiting for the transaction to finish. Any ideas ?
I've tried seemingly everything. Setting hibernate's autocommit mode to true, setting the locktype when executing the queries to pessimistic read/writes, sending over query hints with the queries with max transaction times, executing the queries in separate JTA transactions, executing them in the same transaction, nothing seems to work, the delete query always 'hangs'

DBLinks ORA-24778: cannot open connections

I have a stored procedure which opens the cursor to fetch the data from remote databse
Cursor crs1 is select distinct ID FROM xxxx#link where xxxx and ID = v_id;
Open crs1;
loop fetch crs1 into v_N_ID;
exit when crs1%notfound;
end loop;
This week we started getting this ORA-24778: cannot open connections error. After restarting the websphere server and call the stored procedure it works 2 or 3 times and then again it fails.
We are using XA and the OPEN_LINKS_PER_INSTANCE is set to default 4.
I dont find any answers based on the discussion here
ORA-24778: cannot open connections
How to fix this issue?

How to count open db connections?

I'm developing a web app using Java servlet to access Mysql db, how can I get the number of connections to my DB that is currently open ?
Edit :
I tried "show processlist", it showed me : 2695159, but that's not right, I'm just developing this new project, I'm the only user, couldn't have that many processes running, what I want is the number of users accessing my project's DB, not the number of all db users, but just the ones logged in to my database which has only one table.
Depending on your MySQL version, you can perform a select on
SELECT COUNT(*) FROM information_schema.PROCESSLIST;
and you can do a where between the user, database, and host IP.
For example:
USE information_schema;
SELECT COUNT(*) FROM PROCESSLIST WHERE db ="mycase" AND HOST LIKE "192.168.11.174%"
You could use the MySQL command show processlist to get the number of connections.
However that'll also show you any connections made with the same userID to the database which may not be coming from your servlet.
In general I would suggest that you're probably better off using a Connection Pool object (see http://java-source.net/open-source/connection-pools) to manage your connections to the MySQL server. This can increase performance by making DB connections persistent, so you don't always have the overhead of a new DB connection for each page load.
If your servlet needs to know the number of connections then your Connection Pool should come with a method that tells you how many connections are currently active.
show status like 'Threads_connected'
or
show global status like 'Threads_connected'
Not sure about the difference between those two in a user-context, and you might still suffer from the problem that you would see all connections, not only those from your app.
you can even check Threads_running to only see running threads (e.g not sleeping).
Run the following query, it lists out host name and no. of connections from each host:
SELECT host,count(host) FROM information_schema.processlist GROUP BY host;
show processlist
You can only select from Information_Schema.Processlist the data that belongs to you. It means you can use it for monitoring ONLY if you're logged in as root, otherwise you will be seeing the connections coming from your user you got logged in with.
If you want proper monitoring SQL, it will be:
SELECT variable_value
FROM INFORMATION_SCHEMA.GLOBAL_STATUS
WHERE variable_name='threads_connected'
You also can count open connection by show the status from Threads_connected variable name like this:
SHOW STATUS WHERE variable_name = 'Threads_connected';
Or you can also count the process list directly from information_schema.PROCESSLIST like below:
SELECT COUNT(*) FROM information_schema.PROCESSLIST;
You may use this
SHOW GLOBAL STATUS;
or
show global status like "Threads_connected";
from Connections status you can findout total number of connections.

Categories