Microsoft SQL Server database locks - sql-server-2012

A lot of times database locks appear on our Microsoft SQL Server database. The blocker query appears as Fetch
API_CURSOR000000000004D888. This string is just a sample. But it is always an API_CURSOR0000000XXXXX some value. We were able to find the SQL query running behind this cursor using steps in articles like
https://www.sqlskills.com/blogs/joe/hunting-down-the-origins-of-fetch-api_cursor-and-sp_cursorfetch/
https://social.msdn.microsoft.com/Forums/en-US/f51618eb-5332-4f10-9985-b343933579da/fetch-apicursor-unusual?forum=sqldatabaseengine
We could find the SQL query that is blocking the database. It looked like this below. Every time it is the same query.
session_id properties creation_time is_open text 200 API | Dynamic | Scroll Locks | Global (0) 05:44.8 1 (#P1 nchar(10))
SELECT *
FROM JDE_PRODUCTION.PRODDTA.F00022 (UPDLOCK)
WHERE (UKOBNM = #P1)
FOR UPDATE OF UKOBNM, UKUKID
I am seeking help here to see if there is a way we can find the actual values that are passed in the variable #P1. Please let me know if someone has ideas or already done this.

no you will not be. rather check with your application team and see how the DB connections are set up.
if its a Docker Image/Container then check the Database URL, there they may have set SelectMethod = Cursor.
with such settings, every query passed via this Connection will make Cursor call to SQL Server which is unnecessary.

Related

SQL select by field acting weird

I am writing this post because I have encountered something truly weird with an SQL statement I am trying to make.
Context:
I am developing an app which uses JPA in the backend to persist / retrieve objects to/from a postgres database.
Problem:
During some tests I have noticed that when a particular user adds entries in the database and later I try to fetch them by his facebook id, the result is an empty list, even though the entries are there in the database. Doing a select statement on the database returns no rows. This does not happen with other users.
I have noticed that the mentioned user's facebook id is slightly longer then others. I do not know if and how this affects this situation.
Interesting part:
When during debugging I created an entry not programmatically, but manually with a SQL INSERT statement directly on the database (marked red on the 1st screenshot), I could fetch the data by facebook id both in my app and with a select statement.
Do you have any ideas what is going on here?
Please check the screenshots:
result of select * from table:
result of select * from table where user_facebook_id = 10215905779020408 :
Please help,
Thanks

Simple queries take very long

When I execute a query for the first time in DBeaver it can take up to 10-15 seconds to display the result. In SQLDeveloper those queries only take a fraction of that time.
For example:
Simple "select column1 from table1" statement
DBeaver: 2006ms,
SQLDeveloper: 306ms
Example 2 (other way around; so theres no server-side caching):
Simple "select column1 from table2" statement
SQLDeveloper: 252ms,
DBeaver: 1933ms
DBeavers status box says:
Fetch resultset
Discover attribute column1
Find attribute column1
Late bind attribute colummn1
2, 3 and 4 use most of the query execution time.
I'm using oracle 11g, SQLDeveloper 4.1.1.19 and DBeaver 3.5.8.
See http://dbeaver.jkiss.org/forum/viewtopic.php?f=2&t=1870
What could be the cause?
DBeaver looks up some metadata related to objects in your query.
On an Oracle DB, it queries catalog tables such as
SYS.ALL_ALL_TABLES / SYS.ALL_OBJECTS - only once after connection, for the first query you execute
SYS.ALL_TAB_COLS / SYS.ALL_INDEXES / SYS.ALL_CONSTRAINTS / ... - I believe each time you query a table not used before.
Version 3.6.10 introduced an option to enable/disable a hint used in those queries. Disabling the hint made a huge difference for me. The option is in the Oracle Properties tab of the connection edit dialog. Have a look at issue 360 on dbeaver's github for more info.
The best way to get insight is to perfom the database trace
Perform few time the query to eliminate the caching effect.
Than repeat in both IDEs following steps
activate the trace
ALTER SESSION SET tracefile_identifier = test_IDE_xxxx;
alter session set events '10046 trace name context forever, level 12'; /* binds + waits */
Provide the xxxx to identify the test. You will see this string as a part of the trace file name.
Use level 12 to see the wait events and bind variables.
run the query
close the conenction
This is important to not trace other things.
Examine the two trace files to see:
what statements were performed
what number of rows was fetched
what time was elapsed in DB
for the rest of the time the client (IDE) is responsible
This should provide you enough evidence to claim if one IDE behaves different than other or if simple the DB statements issued are different.

Tagging an SQL Query

I would like to be able to tag an SQL query somehow, so I can relate the query execution to the web request that triggered the query. I already have a unique request id, that I tag my logs and other monitoring with, so I can easily do a complete trace across the weblogs and new relic for example.
But when I look at a report of long running SQL queries for example, I cannot trace that back to the request that triggered the SQL Query. I would really like to be able to tag the query with my request id somehow.
I can't find anything online. When I search I just find blogs about storing tags and tag clouds in SQL. Not really what I need.
Hope the question makes sense.
This is a very interesting post...
I hope, adding an extra nullable parameter to your stored procedure(s) will ensure that the profiler will catch the unique id passed during a call (in the trace) whether you use that parameter inside the procedure or not (i.e. to do something meaningful...like inserting into an audit table with unique id, procedure name, timestamp etc).
But I think that will make life difficult as you now have to update all your procedures.
If you already have logging turned on (web server) and it captures the same unique id in its request (log file) along with a timestamp then you probably can code a small utility app that reads the log file and find matching entries in the traced table by the timestamp alone.
The only thing that might go wrong is if your web server and database server have differeing times (you need to offset your calculation accordingly).
I don't know if this will help but it is certainly a very interesting project and I am hoping somebody have experienced this thing and came up with a nice solution.
Will be closely watching this post if such a solution exists....
All the best...
If I understand correctly, you want to follow up the query execution in Activity Monitor. But have you considered using a DMV or SQL PROFILER ?
In my opinion, your best bet would be to wrap it in a stored proc. This way you will be able to FILTER your trace only for this object. Here's an example of a simple select and the same select wrapped in stored proc named sproc1 :
As you can see in this image, you can start a SQL PROFILER trace and filter it on the ObjectName. You can then add other column like CPU, StartTime, ...
If you can't use a stored proc, then I would suggest to insert a comment before the exec like this:
/* ID1234 */
select * from table1
Then use SQL PROFILER the same way but you now filter on the TextData using your ID
Here the result :

JDBC and SQL+ return different results on Oracle DB

Query in question:
select count(*) from test m where m.IND_1 is not null AND m.IND_2 is null
This query will return 1 using SQL+, and 0 through a JDBC template. I expect 1 to be the correct result.
All the usual suspects have been checked (for instance, is DB the correct one, same user is used and so on).
Does anyone have any similar experience?
Yes, I sometimes forget to "COMMIT" something from SQL editors with AutoCommit disabled. Then in this editor session I got my changes, but in other sessions they were not visible.
Try to check it from other session, even from SQL+ running on other machine.

SQL query giving wrong result on linked server

I'm trying to pull user data from 2 tables, one locally and one on a linked server, but I get the wrong results when querying the remote server.
I've cut my query down to
select * from SQL2.USER.dbo.people where persId = 475785
for testing and found that when I run it I get no results even though I know the person exists.
(persId is an integer, db is SQL Server 2000 and dbo.people is a table by the way)
If I copy/ paste the query and run it on the same server as the database then it works.
It only seems to affect certain user ids as running for example
select * from SQL2.USER.dbo.people where persId = 475784
works fine for the user before the one I want.
Strangely I've found that
select * from SQL2.USER.dbo.people where persId like '475785'
also works but
select * from SQL2.USER.dbo.people where persId > 475784
brings back records with persIds starting at 22519 not 475785 as I'd expect.
Hope that made sense to somebody
Any ideas ?
UPDATE:
Due to internal concerns about doing any changes to the live people table, I've temporarily moved my database so they're both on the same server and so the linked server issue doesn't apply. Once the whole lot is migrated to a separate cluster I'll be able to investigate properly. I'll update the update once this happens and I can work my way through all the suggestions. Thanks for your help.
The fact that LIKE operates is not a major clue: LIKE forces integers to string (so you can say WHERE field LIKE '2%' and you will get all records that start with a 2, even when field is of integer type). Your incorrect comparisons would lead me to think your indexes are corrupt, but you say they work when not used via the link... however, the selected index might be different depending on the use? (I seem to recall an instance when I had duplicate indexes and only one was stale, although that was too long ago to recall the exact cause).
Nevertheless, I would try rebuilding your index using the DBCC DBREINDEX (tablenname) command. If it turns out that doing so fixes your query, you may want to rebuild them all: here is a script for rebuilding them all easily.
Is dbo.people a table or a view? I've seen something similar where the underlying table schema had been changed and dropping and recreating the view fixed the problem, although the fact that the query works if run directly on the linked server does indicate something index based..
Is the linked server using the same collation? Depending on the index used, I could see something like this perhaps happening if the servers were not collation compatible, but the linked server was set up with collation compatible (which tells Sql Server it can run the query on the remote server).
I would check the following:
Check your definition on the linked server, and confirm that SQL2 is the
server you expect it to be
Check and compare the execution plans both from the remote and local servers
Try linking by IP address rather than name, to ensure you have the proper machine
Put the code into a stored procedure on the remote machine, and try calling that instead
Sounds like a bug to me - I;ve read of some issues along these lines, btu can't remember specifically what. What version of SQL Server are you running?
select * from SQL2.USER.dbo.people where persId = 475785
for a PersID which fails how does:
SELECT *
FROM OpenQuery(SQL2, 'SELECT * FROM USER.dbo.people WHERE persId = 475785')
behave?