How to lock when creating table in sql server? - java

I'm trying to run this query on a multiple instances (on a server) of the same application
I tried to run the query but would get deadlocks.
set transaction isolation level serializable
go
begin transaction
if not exists (select name from sys.sysobjects where name like 'xyp')
begin
CREATE TABLE xyp( id varchar(1), name varchar(5));
end
commit transaction go
Is there anything that I can do?

Why you need to lock the table during the creation? i don't think it can be done in sql server. you need to make some changes against your app.

Related

How to get postgres schema from runinng query in Java

assume you do query on pg_stat_activity table and you get example result:
datid
datname
pid
usesysid
usename
application_name
client_addr
client_hostname
client_port
backend_start
xact_start
query_start
state_change
wait_event_type
wait_event
state
backend_xid
backend_xmin
query
backend_type
7198
10
rdsadmin
7195
16384
rdsadmin
32375
10
rdsadmin
PostgreSQL JDBC Driver
16409
c-t-s
21143
16410
c-t-s
c-t-s
10.10.3.1
48037
2021-01-18 13:19:03
2021-01-18 13:31:23
2021-01-18 13:31:23
Client
ClientRead
idle
COMMIT
client backend
I would like to know on which schema the query COMMIT was executed?
My case is i have schema-based multitenancy and i would like to distinguish between schemas (tenants). We always make a single-schema queries, so we dont mix them. To achieve that we set search_path on each getConnection method invocation. Code is developed in java and we dont use schema names in queries, as it is always dynamic -- taken from current request context and set in getConnection method.
With current result I dont know which tenant (schema) is causing slow / long queries.
I have tried to select from pg_class by ids taken from pg_stat_activity but without luck.
So far the comments did not answer my problem, is that possible at all?

How to make Hibernate #Lock annotation work for Oracle DB?

I stumbled upon a problem with locking row in Oracle DB. The purpose of the lock is to prevent more than one transaction reading data from the DB because this data influences the generation of new data and is changed in terms of a transaction.
In order to make the lock, I've put the #Lock annotation over SpringData find method which retrieves data that participates in the transaction.
#Lock(LockModeType.PESSIMISTIC_WRITE)
User findUserById(#Param("id") String operatorId);
After this code is implemented I get log message
org.hibernate.loader.Loader - HHH000444: Encountered request for locking however dialect reports that database prefers locking be done in a separate select (follow-on locking); results will be locked after initial query executes
Besides, it has no effect and causes
org.springframework.dao.DataIntegrityViolationException: could not execute batch; SQL [insert into ...]
The issue can be solved when rewriting the lock using entity manager
entityManager.lock(userByIdWithLockOnReadWrite, LockModeType.PESSIMISTIC_WRITE);
or
entityManager.unwrap(Session.class).lock(userByIdWithLockOnReadWrite, LockMode.PESSIMISTIC_WRITE);
The issue doesn't appear on MariaDB (MySQL).
Maybe there are some special rules of using the annotation?
You said that:
The purpose of the lock is to prevent more than one transaction
reading data from the DB because this data influences the generation
of new data and is changed in terms of a transaction.
Oracle uses MVCC (Multiversion Concurrency Control) so Readers don't block Writers and Writers don't block Readers. Even if you acquire a row-level lock with Oracle, and you modify that row without committing, other transactions can still read the last committed value.
Related to this log message:
org.hibernate.loader.Loader - HHH000444: Encountered request for locking however dialect reports that database prefers locking be done in a separate select (follow-on locking); results will be locked after initial query executes
The follow-on locking mechanism is due to Oracle not being able to apply the lock when doing Oracle 11g pagination, using DISTINCT or UNION ALL.
If you're using Oracle 12i, then you can update the Hibernate dialect to Oracle12cDialect and pagination and locking will work fine since Oracle 12 uses the SQL standard pagination and it no longer requires a derived table query.
This does not happen in MariaDB or any other database. It's just an Oracle pre-12 limitation.
If you are using Hibernate 5.2.1, we added a new hint HINT_FOLLOW_ON_LOCKING which disables this mechanism.
So, your Spring Data query becomes:
#QueryHints(value = { #QueryHint(name = "hibernate.query.followOnLocking", value = "false")}, forCounting = false)
#Lock(LockModeType.PESSIMISTIC_WRITE)
User findUserById(#Param("id") String operatorId);
you can also apply it manually:
User user = entityManager.createQuery(
"select u from User u where id = :id", User.class)
.setParameter("id", id);
.unwrap( Query.class )
.setLockOptions(
new LockOptions( LockMode.PESSIMISTIC_WRITE )
.setFollowOnLocking( false ) )
.getSingleResult();
Is there any option to make a Transaction(TxB) to wait for some time (without throwing Lock Acquisition Exception) for another Transaction(TxA) to release the Lock.

Java Connection String to query from two database

I am having a problem. I have a query that checks one database table and updates another database table. I am using MySQL 5.1
UPDATE dldd.temp,test.temp
SET test.temp.name = dldd.temp.word
WHERE dldd.temp.id = test.temp.id
this is my SQL statement that is working fine. Now I want to execute this statement using Java PreparedStatement . The problem is I don't know how to write the Connection String to select two database i.e
"jdbc:mysql://localhost:3306/"+dbname+"?characterEncoding=UTF-8"
What should come in place of dbname. Can I select multiple db there.
Have a look at http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html.
If the database is not specified, the connection is made with no default database. In this case, either call the setCatalog() method on the Connection instance, or fully specify table names using the database name (that is, SELECT dbname.tablename.colname FROM dbname.tablename...) in your SQL. Opening a connection without specifying the database to use is generally only useful when building tools that work with multiple databases, such as GUI database managers.

How to achieve Multiple Consumer Application for Shared Database (Multitenancy)?

Below Snapshot is current application flow.
Current Flow
When user Logged in at these multiple deployments, then respective SMSAgent(java class) insert user info in database, SMSHelper is a java Scheduler which reads data from database in its local queue,send SMS and then update user status in database.
Issue with this flow
Now,In above scenario, Multiple SMS is getting send to Single User because database is common and both the notification helper takes contact details from database(which may be common) and send SMS to that user.
Existing Solution
Currently, solution to this problem is only available in oracle 11g where select query has for update skip locked support.
Expectation
How to achieve the same with all databases at application level and not at query level ?
First,you have to RESERVE the row by update and then do select.
Suppose u have 200 row,
so first you should do is RESERVE by some value which are unique by instance, also you could limit on no of rows updated in your query and then select the row which are reserved by your query
UPDATE TABLE_NAME SET SERVER_INSTACE_ID=UNIQUE_VAL AND ROWNUM <= RECORD_RESERVATION_LIMIT
SELECT * FROM TABLE_NAME WHERE SERVER_INSTANCE_ID=UNIQUE_VAL
Through this approach, you don't need to obtain lock on row or table.

Change Table names in derby database using entitymanager

I am using an APACHE DERBY database, and basing my database interactions on EntityManager, and I don't want to use JDBC class to build a query to change my tables' names (i just need to put a prefix to each new user to the application, but have the same structure of tables), such as:
//em stands for EntityManager object
Query tableNamesQuery= em.createNamedQuery("RENAME TABLE SCHEMA.EMP_ACT TO EMPLOYEE_ACT");
em.executeUpdate();
// ... rest of the function's work
// The command works from the database command prompt but i don't know how to use it in a program
//Or as i know you can't change system tables data, but here's the code
Query tableNamesQuery= em.createNamedQuery("UPDATE SYS.SYSTABLES SET TABLENAME='NEW_TABLE_NAME' WHERE TABLETYPE='T'");
em.executeUpdate();
// ... rest of the function's work
My questions are :
This syntax is correct?
Will it work?
Is there any other alternative?
Should I just use the SYS.SYSTABLES and find all the tables that has 'T' as tabletype and alter their name their, will it change the access name ?
I think you're looking for the RENAME TABLE statement: http://db.apache.org/derby/docs/10.10/ref/rrefsqljrenametablestatement.html
Don't just issue update statements against the system catalogs, you will corrupt your database.

Categories