web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Microsoft Dynamics AX (Archived)

Deadlock when posting timesheets

(0) ShareShare
ReportReport
Posted on by

We have an import process that reads from a text file (two variations - one CSV, the other XML) into a temp table. Then the temp table is read and we write to TSTimesheetTable, TSTimesheetLine, TSTimesheetLineWeek, and there's call to TSTimesheetTrans::updateFromTimesheetLineWeek. These are inside a tts block, and all the data seems fine.

We then run some validations - emplId valid, employee assigned to project, hours per day, and so on. Valid timesheets are then posted.

Posting is done by updating TSTimesheetTable, setting ApprovalStatus to TsAppStatus::Ready, then calling TSCreateProjJournal::create(TSTimesheetTable).

Occasionally - we're talking months between occurrences - the post fails with an error that there's a deadlock. It has also happened for timesheets that are not imported through this process, which go through workflow, with the same error. The error message is, "Cannot delete a record in Ledger balances - Dimensions (LedgerBalancesTransDelta). Ledger account: , . Deadlock, where one or more users have simultaneously locked the whole table or part of it."

We're running AX 2009, Rollup Update 4. Production environment has three AOS instances. We have not been able to recreate the deadlock situation in our test environment, which is only a single AOS. I did try locking the entire table with a SQL script in SSMS, but that just made the AX job wait; after 7 minutes or so, I continued my script in SSMS, releasing the table lock, and the AX job immediately resumed and completed quickly.

One thing that seems suspicious in the error message is the "Ledger account , ." Almost seems like a strfmt with substitution variables that are blank.

I've followed the call stack in debug, all the way down to LedgerBalancesPostingList class methods and LedgerBalancesTransDelta methods. LedgerBalancesTransDelta (lbtd) is, for the most part, not referred to directly. Posting goes through a RecordSortedList that is setup for lbtd, and there's an insert_database() form the RSL. Then there are insert_recordset calls using the lbtdSum view in a select, into two tables. The only direct reference to lbtd is a delete_from, which clears out lbtd by the UserTTSId. In all methods where I could see it, the ttsId was the same.

Another odd thing I found was, after the RSL.insert_database(), I could not see any rows in SQL Server (SELECT *, no WHERE condition), nor could I see any rows by opening lbtd from the AOT. It's almost behaving like a temporary table, but as far as I can tell, it's not temporary in the properties, and I don't see it being made temporary in code anywhere.

Has anyone else seen anything like this? Any ideas on how I can simulate a lock on lbtd, to be able to recreate the problem in test?

*This post is locked for comments

I have the same question (0)
  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at

    Deadlocks are all about concurrency and order of operations - two processes are blocking each other, because they're both waiting for resources held by the other process. They would wait forever if there was no deadlock detection. Mere waiting for a resource (such as when you locked the table) is not a deadlock.

    What you should really do is to activate tracing flags for deadlocks in your SQL server - when a deadlock occurs, logs will show you which locks caused the deadlock, queries that locked resources and so on. That will help you understand much better what happened. See Detecting and Ending Deadlocks for more information.

    I would have to look to AX (which I can't right now) to be able to comment any details about LedgerBalancesTransDelta table.

  • Community Member Profile Picture
    on at

    Thanks for your reply Martin. I tried to tell them we needed record locks, that locking the table wouldn't work, but they insisted I should try it anyway. We'll take a look at the SQL tracing that you suggested.

  • Community Member Profile Picture
    on at

    Hmm... guess I never actually tried this before. Created some sandbox methods. Turns out that all database methods inside a transaction are not visible until they're committed. Didn't matter if they came from RecordSortedList.insertDatabase(), or from normal table.insert(). Didn't matter if I look in SQL Server Mgmt Studio, or an AOT browse.

    This suggests it will be exceedingly difficult to intentionally recreate the deadlock situation on LedgerBalancesTransDelta, since we can't see what the rows are. With Connection and UserConnection in play, I can conceive a scenario where a thread could deadlock itself, but then it should happen every time, and not ever few months as we've seen.

    The only other possibility I can think of, is that the UserTTSId on LedgerBalancesTransDelta is somehow getting the same value for transactions in two different threads (completely different jobs, sessions, ...). With three AOS instances, could that be possible? [But, even so, I don't see any updates to LedgerBalancesTransDelta, only inserts from the RecordSortedList, and deletes via delete_from.]

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > 🔒一 Microsoft Dynamics AX (Archived)

#1
Martin Dráb Profile Picture

Martin Dráb 4 Most Valuable Professional

#1
Priya_K Profile Picture

Priya_K 4

#3
MyDynamicsNAV Profile Picture

MyDynamicsNAV 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans