エラー メッセージ "query did not return a unique result" が返される、Confluence でのユーザー関連の問題
プラットフォームについて: Server および Data Center のみ。この記事は、Server および Data Center プラットフォームのアトラシアン製品にのみ適用されます。
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.
*Fisheye および Crucible は除く
問題
Confluence で次の問題が確認される。
- ユーザーが Confluence にログインできない
- 特定のユーザーが Confluence にログインできない
- ユーザー ディレクトリの同期に失敗する
UI と atlassian-confluence.log:
に次のエラーが表示されます。
org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 2
原因
このエラーは、データベースの重複値によって発生します。次のような原因が考えられます。
- ディレクトリ キャッシュの何らかの破損
- データベースの破損
- Missing unique constraints in the database. Some versions of Confluence introduced missing unique constraints upon installation. This persists throughout Confluence upgrade. This issue is mentioned here and is fixed in Confluence 7.1 CONFSERVER-58261 - Missing unique constraints and index in certain fresh Confluence installation
診断 1 - 影響を受けたテーブルの確認
この問題を診断するにはログのエラー メッセージを確認し、それに続くスタック トレースに次のいずれかが含まれるかどうかを確認します。
1. com.atlassian.crowd.embedded.hibernate2.HibernateUserDao.internalFindUser
2. com.atlassian.confluence.user.persistence.dao.hibernate.HibernateConfluenceUserDao.findByUsername
3. com.atlassian.crowd.embedded.hibernate2.HibernateGroupDao.internalFindByName
例 - 1 つめの問題の影響を受けている場合は次のスタック トレースが表示されます。
2018-03-01 09:34:39,537 INFO [Caesium-1-4] [atlassian.crowd.directory.DbCachingRemoteDirectory] synchroniseCache failed synchronisation complete for directory [ 884738 ] in [ 101138ms ]
2018-03-01 09:34:39,600 ERROR [Caesium-1-4] [atlassian.crowd.directory.DbCachingDirectoryPoller] pollChanges Error occurred while refreshing the cache for directory [ 884738 ].
org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 2; nested exception is org.hibernate.NonUniqueResultException: query did not return a unique result: 2
at org.springframework.orm.hibernate5.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:256)
at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:362)
at org.springframework.orm.hibernate5.HibernateTemplate.execute(HibernateTemplate.java:313)
at com.atlassian.crowd.embedded.hibernate2.HibernateUserDao.internalFindUser(HibernateUserDao.java:541)
- 1 つめのスタック トレースが見つかった場合、cwd_user テーブルに重複したレコードがあります。以降の診断 2 に進み、重複したユーザーを見つけます。
- 2 つめのスタック トレースが見つかった場合、user_mapping に重複したレコードがあります。次のページに進んでください。
- 3 つめのスタック トレースが見つかった場合、cwd_group テーブルに重複したレコードがあります。次のページに進んでください。
診断 2 - cwd_user テーブルで重複ユーザーを見つける
診断クエリ - 1: 同じ外部 ID を持ち同じディレクトリに所属する重複ユーザーを cwd_user
テーブルで見つけます。
SELECT directory_id, external_id
FROM cwd_user
GROUP BY directory_id, external_id
HAVING ( COUNT(external_id) > 1)
診断クエリ - 2: 同じ lower_user_name
を持ち同じディレクトリに所属する重複ユーザーを cwd_user
テーブルで見つけます。
SELECT lower_user_name, directory_id
from cwd_user
GROUP BY lower_user_name, directory_id
HAVING (COUNT(lower_user_name) > 1);
ソリューション 1 - MS SQL データベース
いずれかのアプリケーション (Confluence/Jira) でデータベースとして MS SQL Server を利用している場合、ソリューションの手順に進む前に、トランザクション分離レベルが "Read Comitted" に設定されていることを確認します (詳細については以降のガイドをご確認ください)。分離レベルが適切に設定されていない場合、アプリケーションをシャットダウンし、分離レベルを以降のガイドに従って修正してからソリューションの手順に進む必要があります。
- SQL Server のデータベース セットアップ - Confluence
ソリューション 2 - ユーザー ディレクトリの再作成
この手順を試す前に、Confluence のデータベースとアプリケーション ディレクトリのバックアップを作成するようにしてください。これにより、問題が発生したときに、Confluence を以前に動作していた状態に戻すことができます。
- Confluence 管理 > [ユーザー ディレクトリ] に移動し、ユーザーが所属するディレクトリの [同期] ボタンをクリックして、ディレクトリを手動で同期します。
- これで問題が修正されない場合、Confluence のユーザー ディレクトリを [ユーザー ディレクトリ] 直下の一番上に配置します。
- Confluence の内部管理者としてログインし、Confluence 管理 > [ユーザー ディレクトリ] に移動して、影響を受けるユーザーが所属するディレクトリを無効化します。
- 古いディレクトリとまったく同じ構成の新しいディレクトリを作成します。
新しいディレクトリを同期し、問題が再発するかどうかをテストします。
対象のユーザー ディレクトリが "Read-only with Local Groups" としてセットアップされている場合、作成する新しいディレクトリではローカルのグループ メンバーシップが保持されないため、それらを再作成する必要があります。これが許容できる状況でない場合はソリューション 3 をお試しください。
対象のユーザー ディレクトリが委任ディレクトリである場合、以降のステップ (4) に従って新しいコピーを作ると、すべてのユーザーがクリアされ、Confluence で不明なユーザーとして表示されます。これは予期された挙動であり、各ユーザーが再ログインしたタイミングで自動的に修正されます。これは、委任ディレクトリでは、ユーザーが初めてログインするまでは Confluence 内にユーザーが作成されないためです。
問題が解決した (ユーザーが期待どおりログインできる) 場合、古いディレクトリを削除して新しいものを保持します。
問題が引き続き発生する場合はソリューション 3 をお試しください。
ソリューション 3 - データベースからユーザーを委任
Confluence のデータを削除したり変更したりする前に、必ずバックアップを作成するようにします。
ステップ 1: 重複したユーザー ID を見つける
次のクエリを実行して、重複しているユーザーのユーザー ID を取得します。
SELECT id, lower_user_name FROM cwd_user WHERE external_id = '<duplicated external_id from diagnostic query>'
または
SELECT id, lower_user_name FROM cwd_user WHERE lower_user_name = '<duplicated username from diagnostic query>'
結果は次のようになります。
ID | user_name |
---|---|
229377 | admin |
229378 | admin |
上記のクエリで返された ID を記録します。次のステップ (ステップ 2) で削除すべきエントリを判断します。
ステップ 2: 重複しているユーザーがグループに所属しているかを確認し、削除する ID を判断する
重複した ID の結果に対して次の SQL クエリを実行します。この SQL クエリは、各重複ユーザーの ID が紐付けられているグループの数を返します。
SELECT count(*), child_user_id FROM cwd_membership WHERE child_user_id in (<duplicated_id_1>,<duplicated_id_2>) GROUP BY child_user_id
ステップ 3.1: 重複 ID のいずれかでグループ メンバーシップの結果が返されない場合
上記の SQL クエリで次のようなものが返される場合、
count(*) | child_user_id |
---|---|
2 | 229377 |
もう片方の重複ユーザー (SQL クエリに表示されていないもの) を安全に削除できます。
DELETE FROM cwd_user_attribute WHERE user_id = <duplicated_id>;
DELETE FROM cwd_user_credential_record WHERE user_id = <duplicated_id>;
DELETE FROM cwd_user WHERE id = <duplicated_id>;
ステップ 3.2: 両方の重複 ID でグループ メンバーシップの数が返されない場合
ステップ 2 の SQL クエリで次のようなものが返される場合、
count(*) | child_user_id |
---|---|
2 | 229377 |
2 | 229378 |
次の SQL クエリを実行して重複したユーザーのグループ メンバーシップを取得できます。
SELECT
u.user_name,
g.id as GroupID,
g.group_name
FROM
cwd_user u
JOIN cwd_membership m
ON
u.id = m.child_user_id
JOIN cwd_group g
ON
g.id = parent_id
WHERE u.user_name = '<duplicated username>'
ORDER BY 2 DESC, 1 ASC;
上記の SQL クエリの結果を記録します。重複したユーザー ID のいずれかを安全に削除できます。次のクエリを順に実行します。
DELETE FROM cwd_membership WHERE child_user_id = <duplicated_id>;
DELETE FROM cwd_user_attribute WHERE user_id = <duplicated_id>;
DELETE FROM cwd_user_credential_record WHERE user_id = <duplicated_id>;
DELETE FROM cwd_user WHERE id = <duplicated_id>;
After removing the duplicates, the constraints in the Workaround section of CONFSERVER-58261 - Missing unique constraints and index in certain fresh Confluence installation will need to be applied to avoid future duplicates. If errors are returned applying any constraint, take a screenshot and open a ticket with Atlassian Support.
Go to the Confluence UI afterward and ensure that the user has correct memberships.