Hi,
Since upgrading from Navision 4.0 to 4.0SP1 my client has been getting the following error message when adding lines to sales orders and purchase orders :
"The Document Dimension table cannot be changed because it is locked by another user"
They are using SQL Server 2000. Has anything been changed in SP1 with regards to SQL locking? Or is there some other explanation?
As I say this was never a problem before the upgrade.
Any help appreciated,
Jonathan Wareham
0
Comments
You can tell Navision to place always record-locks: File=>Database=>Alter=>Tab Advanced=>"Always Rowlocks".
I am not sure but this can also slow down performance.
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!
Kriki's solution may work, but may also cause unanticipated performance issues.
If this is what is going on, it is probably not the user that is entering the lines, they can't move that fast, and you probably don't have that many dimensions (I hope for your sake).
It is probably the result of another users simultaneous activities such as posting. This issue can be made worse by flow fields. The SQL handling of these fields can frequently cause escalation to table locks during activities such as posting.
You might want to check and see if you have SIFT fields associated with this table. If so, it could be a factor and you might want to consider turning off the SIFT maintenance.
Under SQL, you will still be able to use the flowfields, but the calculation will be done when the field is accessed rather than when it is stored/modified etc. If you find this to be the case, leave the key, turn off the SIFT maintenance and you will probably enjoy the outcome.
If "Update on posting" is checked for some analysis view, there may be a situation, when deadlock occurs - both posting process and view update tries to write to dimension tables...
BTW, its generally adviced to turn off these "view updates on posting", because it slows down all posting processes, which are done far more often than analysis jobs - users must simply remember to update views before doing some view-based reporting to get the most recent data.
MCP, Dynamics NAV - Application
1. Make sure the clustered index on the Document Dimension table exists. There were some issues with this in 4.01. Without this SQL will do a table scan and lock all the records
2. The current clustered index on Document Dimension has a high density and low selectivity and can cause more records to be locked than need to be.
,[Document Type],[Document No_],[Line No_],
[Dimension Code]
is not very unique you may want to try putting [Document No_] as the first field in the index to lower the density and increase selectivity which should help increase concurrency
3. Memory issues on the SQL Box. As memory utilization increase on the SQL Box it will start to escalate locks. One rowlock takes as much memory as one page lock or table lock. So if there are 100s or 1000s of individual rowlocks on a table and SQL begins to run out of memory it will escalate those locks to page or table locks to help free up memory.
4. As stated above "always rowlock' should only be used if you have A LOT of memory available on SQL Server.
Hope that helps
I believe that I maybe have found the solution to this problem. I will describe this for you tomorrow when I'm back at work.
The solution I received was to do the following changes in codeunit 408:
==============================================================
Codeunit 408
Fct. SaveDocDim. and SaveProdDocDim
Move the current calls to UpdateLineDim to the following places
FUNCTION = SaveDocDim:
GetGLSetup;
IF ShortcutDimCode <> '' THEN BEGIN
IF DocDim.GET(
TableID,DocType,DocNo,
LineNo,GLSetupShortcutDimCode[FieldNumber])
THEN BEGIN
xRecRef.GETTABLE(DocDim);
DocDim.VALIDATE("Dimension Value Code",ShortcutDimCode);
DocDim.UpdateLineDim(DocDim,FALSE); //MOVED LINE
DocDim.MODIFY;
RecRef.GETTABLE(DocDim);
ChangeLogMgt.LogModification(RecRef,xRecRef);
END ELSE BEGIN
DocDim.INIT;
DocDim.VALIDATE("Table ID",TableID);
DocDim.VALIDATE("Document Type",DocType);
DocDim.VALIDATE("Document No.",DocNo);
DocDim.VALIDATE("Line No.",LineNo);
DocDim.VALIDATE("Dimension Code",GLSetupShortcutDimCode[FieldNumber]);
DocDim.VALIDATE("Dimension Value Code",ShortcutDimCode);
DocDim.UpdateLineDim(DocDim,FALSE); //MOVED LINE
DocDim.INSERT;
RecRef.GETTABLE(DocDim);
ChangeLogMgt.LogInsertion(RecRef);
END;
END ELSE
IF DocDim.GET(
TableID,DocType,DocNo,LineNo,GLSetupShortcutDimCode[FieldNumber])
THEN BEGIN
RecRef.GETTABLE(DocDim);
DocDim.UpdateLineDim(DocDim,TRUE); //MOVED LINE
DocDim.DELETE;
ChangeLogMgt.LogDeletion(RecRef);
END;
FUNCTION = SaveProdDocDim:
GetGLSetup;
IF ShortcutDimCode <> '' THEN BEGIN
IF ProdDocDim.GET(
TableID,DocStatus,DocNo,
DocLineNo,LineNo,GLSetupShortcutDimCode[FieldNumber])
THEN BEGIN
xRecRef.GETTABLE(ProdDocDim);
ProdDocDim.VALIDATE("Dimension Value Code",ShortcutDimCode);
ProdDocDim.UpdateLineDim(ProdDocDim,FALSE); //MOVED LINE
ProdDocDim.MODIFY;
RecRef.GETTABLE(ProdDocDim);
ChangeLogMgt.LogModification(RecRef,xRecRef);
END ELSE BEGIN
ProdDocDim.INIT;
ProdDocDim.VALIDATE("Table ID",TableID);
ProdDocDim.VALIDATE("Document Status",DocStatus);
ProdDocDim.VALIDATE("Document No.",DocNo);
ProdDocDim.VALIDATE("Document Line No.",DocLineNo);
ProdDocDim.VALIDATE("Line No.",LineNo);
ProdDocDim.VALIDATE("Dimension Code",GLSetupShortcutDimCode[FieldNumber]);
ProdDocDim.VALIDATE("Dimension Value Code",ShortcutDimCode);
ProdDocDim.UpdateLineDim(ProdDocDim,FALSE); //MOVED LINE
ProdDocDim.INSERT;
RecRef.GETTABLE(ProdDocDim);
ChangeLogMgt.LogInsertion(RecRef);
END;
END ELSE
IF ProdDocDim.GET(
TableID,DocStatus,DocNo,
DocLineNo,LineNo,GLSetupShortcutDimCode[FieldNumber])
THEN BEGIN
RecRef.GETTABLE(ProdDocDim);
ProdDocDim.UpdateLineDim(ProdDocDim,TRUE);//MOVED LINE
ProdDocDim.DELETE;
ChangeLogMgt.LogDeletion(RecRef);
END;
==============================================================
sorry for bringing up old thread, but I just want a one confirmation: this message in first post - is this a message about deadlock occuring, and one transaction being killed, or is this a message saying that a simple lock was taking place and it's timeout has expired? If it's first case, then it's bugs in code, if it's second, then it's simple valid table block occuring, and increasing timeout value might help - correct?
RIS Plus, LLC
MVP - Business Apps
thanks!
RIS Plus, LLC
MVP - Business Apps
RIS Plus, LLC
MVP - Business Apps
I agree that better performance = better. That's no brainer there.
Sometimes better performance = not really possible.
You spend a vast amount of resources optimizing for existing hardware and do whatever is possible (with given set of resources).
You're left with whatever performance you have.
At that point, waiting is most of the time better than retrying. It's simply more time efficient.
Increasing the lock timeout (or turning it off completely) is simply not the right thing to do. Let the message come up and give the user the opportunity to work on something else. Most of the time they know who is heavy on the system, and most of the time the really big processes will have been planned during 'off hours' anyway. I'm sorry but I will not concede that point. Every single time I have seen customers try this, they have changed it back within a day or two. This is from personal experience, onsite at customer sites, not thinking about this from a distant desk.
RIS Plus, LLC
MVP - Business Apps
A very good example has been posted in one of the threads, where user had to keep reentering tracking lines, simply because their transaction was aborted due to lock time out, and poor implementation dropped all temporary data. This gets cumbersome quite fast.
And yes, user education level does have a very big play in all of this - if user knows, that this wait is valid, and he's standing in line sometimes it's much better to just go and make some coffee, instead of poking around and giving a shot at it at random times.
Then again, perhaps that's just my experience with live, on site customer databases and customers themselves
Just my 2 cents.
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!
When the user knows that it should show the message after 10 seconds, and it doesn't, then they know that the process is running instead of waiting, and they leave it alone. They don't want to be waiting for nothing. They actuall appreciate it that the process is kicked back to them, knowing that the most they'll be waiting is however long that setting is.
All users know that the system sometimes locks up, and there is always discussion about it. At some point, there is consensus about how long the timeout should be, and that is when users accept the situation. For one company it is 10 seconds, another has it at 30 seconds, and I've seen one turn it off completely too (only to turn it back on after a couple of days). Increasing it from there is simply not the right thing to do.
RIS Plus, LLC
MVP - Business Apps