Migration from samAccountName to UserPrinicipalName can cause performance issues in Jira
Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.
Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
At times, organizations might switch to the UserPrincipalName based on email address from their current samAccountName in LDAP for user lookup, to align with user management principles in other applications. This might cause a couple of problems for Jira.
It might create a new user account when not done properly Modifying LDAP username or SAMAccountName creates a new user account in Jira Data Center
It can break user mentions JRASERVER-63858 - Mentions are broken when you changed the User Name Attribute from sAMAccountName to userPrincipalName
Additionally, it can cause performance problems while loading rapid board, which this knowledge based will address.
Environment
Jira 8.x
Diagnosis
Right after the switch over to UserPrincipalName based on email address is done under the Administration - > User Management - > user directories, a full sync for that directory is performed by Jira. It incorporated the username rename to email address in both the cwd_user and app_user table correctly, if the proper steps are followed while filling in User Unique ID Attribute and User Unique ID Attribute. Once the synchronization is complete, users complain of performance problems in loading certain rapid boards. Generating a thread dump we can see a lot of time is spent on the database in resolving user details
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.readInternal(IOBuffer.java:1003)
......
- locked <0x00000006ae1b0230> (a com.microsoft.sqlserver.jdbc.TDSReader)
at com.microsoft.sqlserver.jdbc.TDSCommand.startResponse(IOBuffer.java:7581)
at com.microsoft.sqlserver.jdbc.TDSCommand.startResponse(IOBuffer.java:7544)
at com.microsoft.sqlserver.jdbc.SQLServerConnection$1ConnectionCommand.doExecute(SQLServerConnection.java:2972)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7194)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2930)
- locked <0x00000006013b9248> (a java.lang.Object)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectionCommand(SQLServerConnection.java:2977)
......
at com.atlassian.jira.transaction.TransactionSupportImpl.begin(TransactionSupportImpl.java:31)
at com.atlassian.jira.transaction.Txn.begin(Txn.java:17)
at com.atlassian.jira.crowd.embedded.ofbiz.db.DefaultOfBizTransaction.withTransaction(DefaultOfBizTransaction.java:26)
at com.atlassian.jira.crowd.embedded.ofbiz.db.DefaultOfBizTransaction.withTransaction(DefaultOfBizTransaction.java:42)
at com.atlassian.jira.crowd.embedded.ofbiz.db.DefaultOfBizTransactionManager.withTransaction(DefaultOfBizTransactionManager.java:9)
at com.atlassian.jira.crowd.embedded.ofbiz.OfBizUserDao.search(OfBizUserDao.java:896)
at com.atlassian.jira.crowd.embedded.ofbiz.DelegatingUserDao.search(DelegatingUserDao.java:124)
at com.atlassian.jira.crowd.embedded.ofbiz.IndexedUserDao.search(IndexedUserDao.java:430)
at com.atlassian.jira.crowd.embedded.ofbiz.DelegatingUserDao.search(DelegatingUserDao.java:124)
at com.atlassian.jira.crowd.embedded.ofbiz.SwitchingUserDao.search(SwitchingUserDao.java:30)
at com.atlassian.crowd.directory.AbstractInternalDirectory.searchUsers(AbstractInternalDirectory.java:702)
at com.atlassian.crowd.manager.directory.DirectoryManagerGeneric.searchUsers(DirectoryManagerGeneric.java:327)
at com.atlassian.crowd.manager.application.SingleDirectorySearchStrategy.searchUsers(SingleDirectorySearchStrategy.java:33)
at com.atlassian.crowd.manager.application.InMemoryEntitySearchStrategy$$Lambda$2986/1835691745.apply(Unknown Source)
at com.atlassian.crowd.manager.application.InMemoryEntitySearchStrategy.searchMerging(InMemoryEntitySearchStrategy.java:53)
at com.atlassian.crowd.manager.application.InMemoryEntitySearchStrategy.search(InMemoryEntitySearchStrategy.java:43)
at com.atlassian.crowd.manager.application.InMemoryEntitySearchStrategy.searchUsers(InMemoryEntitySearchStrategy.java:34)
at com.atlassian.crowd.manager.application.ApplicationServiceGeneric.searchUsers(ApplicationServiceGeneric.java:715)
at com.atlassian.crowd.embedded.core.CrowdServiceImpl.searchUsers(CrowdServiceImpl.java:174)
at com.atlassian.crowd.embedded.core.CrowdServiceImpl.search(CrowdServiceImpl.java:159)
at com.atlassian.jira.bc.user.search.DefaultUserPickerSearchService.findUserKeysByFullName(DefaultUserPickerSearchService.java:555)
at com.atlassian.jira.jql.resolver.UserResolverImpl.getUsersFromFullNameOrEmail(UserResolverImpl.java:82)
at com.atlassian.jira.jql.resolver.UserResolverImpl.getIdsFromName(UserResolverImpl.java:43)
at com.atlassian.jira.jql.resolver.UserIndexInfoResolver.getIndexedValues(UserIndexInfoResolver.java:31)
at com.atlassian.jira.jql.query.AbstractOperatorQueryFactory.getIndexValues(AbstractOperatorQueryFactory.java:54)
at com.atlassian.jira.jql.query.AbstractEqualityQueryFactory.createQueryForMultipleValues(AbstractEqualityQueryFactory.java:44)
at com.atlassian.jira.jql.query.GenericClauseQueryFactory.getQuery(GenericClauseQueryFactory.java:57)
at com.atlassian.jira.jql.query.AssigneeClauseQueryFactory.getQuery(AssigneeClauseQueryFactory.java:32)
at com.atlassian.jira.jql.query.ContextAwareQueryVisitor.visit(ContextAwareQueryVisitor.java:98)
at com.atlassian.jira.jql.query.ContextAwareQueryVisitor.visit(ContextAwareQueryVisitor.java:27)
at com.atlassian.query.clause.TerminalClauseImpl.accept(TerminalClauseImpl.java:143)
at com.atlassian.jira.jql.query.QueryVisitor.createQuery(QueryVisitor.java:51)
at com.atlassian.jira.jql.query.SavedFilterClauseQueryFactory.getQueryFromSavedFilter(SavedFilterClauseQueryFactory.java:91)
at com.atlassian.jira.jql.query.SavedFilterClauseQueryFactory.getQuery(SavedFilterClauseQueryFactory.java:64)
at com.atlassian.jira.jql.query.ContextAwareQueryVisitor.visit(ContextAwareQueryVisitor.java:98)
........
at com.atlassian.greenhopper.service.issue.IssueDataServiceImpl.findWithServiceOutcome(IssueDataServiceImpl.java:72)
at com.atlassian.greenhopper.web.rapid.work.WorkDataFactory.getWorkDataIssueCountAndLastUpdated(WorkDataFactory.java:255)
at com.atlassian.greenhopper.web.rapid.work.WorkDataFactory.getAllData(WorkDataFactory.java:147)
The sql logs collected while the rapidboard loads show a lot of queries numbering in thousands, of the following type being fired to the database.
1
2
uiaq1c /rest/greenhopper/1.0/xboard/work/allData.json 3ms "SELECT sq_.user_name FROM (SELECT user_name, ROW_NUMBER() OVER (ORDER BY lower_user_name) rnum FROM dbo.cwd_user WHERE (lower_display_name = '<username>' ) AND (directory_id = '10000' )) sq_ WHERE sq_.rnum <= 1000"
uiaq1c /rest/greenhopper/1.0/xboard/work/allData.json 3ms "SELECT sq_.user_name FROM (SELECT user_name, ROW_NUMBER() OVER (ORDER BY lower_user_name) rnum FROM dbo.cwd_user WHERE (lower_display_name = '<username>' ) AND (directory_id = '1' )) sq_ WHERE sq_.rnum <= 1000"
Cause
Each Rapidboard is created out of filter and these filter are JQLs that gather the issues that satisfy the criteria defined in the JQL. The Rapidboard filter JQL might contain hardcoded assignee names like below. The filter IDs used in the JQL above by itself could have a JQL with hardcoded assignee or reporter names.
1
2
Project = TEST and issuetype = bug and assignee in (svenk,tomsay,whoistat)
Project = DEV and issuetype = Task and filter in (56943, 34345, 23454)
The switch from the SamAccountName to UserPrincipalName caused the user name to be changed to email addresses. So this causes Jira to not able to resolve the assignee name directly. So it looks up the user by either display name or email address repeatedly for all the users who are hardcoded in the filter and quick filters of the board, from each directory as shown in the sql logging above. Below is the snippet where its not able to resolve the user name and attempting find by email or display name
1
2
3
4
5
at com.atlassian.jira.bc.user.search.DefaultUserPickerSearchService.findUserKeysByFullName(DefaultUserPickerSearchService.java:555)
at com.atlassian.jira.jql.resolver.UserResolverImpl.getUsersFromFullNameOrEmail(UserResolverImpl.java:82)
at com.atlassian.jira.jql.resolver.UserResolverImpl.getIdsFromName(UserResolverImpl.java:43)
at com.atlassian.jira.jql.resolver.UserIndexInfoResolver.getIndexedValues(UserIndexInfoResolver.java:31)
at com.atlassian.jira.jql.query.AbstractOperatorQueryFactory.getIndexValues(AbstractOperatorQueryFactory.java:54)
Solution
Identify the rapidboard filters that might have the performance issue. Look for any hardcoded assignee or reporter or watchers in them with a query and fix them. Replace the usernames in the filters with their corresponding upn(email addresses).
1 2 3
select "ID","SAVED_FILTER_ID" from "AO_60DB71_RAPIDVIEW" where "NAME" like '%<board name>%'; select * from searchrequest where ID = <SAVED_FILTER_ID from above>; select * from "AO_60DB71_QUICKFILTER" where "RAPID_VIEW_ID" = <ID from the RAPIDVIEW>;
Avoid making the switch to the UserPrincipalName if there are too many filters with hardcoded user names.
Was this helpful?