外部ディレクトリとの同期が、エラー "query did not return unique result" で失敗する
プラットフォームについて: Data Center - この記事は、Data Center プラットフォームのアトラシアン製品に適用されます。
このナレッジベース記事は製品の Data Center バージョン用に作成されています。Data Center 固有ではない機能の Data Center ナレッジベースは、製品のサーバー バージョンでも動作する可能性はありますが、テストは行われていません。サーバー*製品のサポートは 2024 年 2 月 15 日に終了しました。サーバー製品を利用している場合は、アトラシアンのサーバー製品のサポート終了のお知らせページにて移行オプションをご確認ください。
*Fisheye および Crucible は除く
問題
外部ディレクトリとの手動同期を行ったときに、同期に失敗し、少数のユーザー/グループのみが Confluence に同期される。
UI と atlassian-confluence.log:
に次のエラーが表示されます。
org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 2
上述のログでは次のスタック トレースを確認できます。
com.atlassian.confluence.user.persistence.dao.hibernate.HibernateConfluenceUserDao.findByUsername
例:
2015-06-23 12:56:20,326 ERROR [scheduler_Worker-5] [atlassian.crowd.directory.DbCachingDirectoryPoller] pollChanges Error occurred while refreshing the cache for directory [ 7864321 ].
org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result: 2
at org.springframework.orm.hibernate.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:590)
at org.springframework.orm.hibernate.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:353)
at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:375)
at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:337)
at com.atlassian.confluence.user.persistence.dao.hibernate.HibernateConfluenceUserDao.findByUsername(HibernateConfluenceUserDao.java:82)
HibernateConfluenceUserDao.findByUsername の文字列が見つからない場合、「Confluence でユーザーに関連する問題が発生し、"query did not return a unique result" エラー メッセージが表示される」をご確認ください。
診断
影響を受けているかどうかを確認するために、1 つめの診断を実行します。1 つめの診断が結果を返さなかった場合にのみ、2 つめの診断を実行します。
診断 1 - user_mapping テーブルの重複した非 null レコード
次のクエリを実行して、user_mapping
テーブルの重複ユーザーを確認します。
SELECT * FROM USER_MAPPING WHERE LOWER_USERNAME IN (SELECT LOWER_USERNAME FROM USER_MAPPING GROUP BY LOWER_USERNAME HAVING COUNT(*) > 1);
これらのクエリが何らかの結果を返す場合、ソリューション 1 に進みます。
これらのクエリが結果を返さない場合、診断 2 に進みます。
診断 2 - user_mapping
テーブルの null レコード
次のクエリを実行して、user_mapping
テーブルの NULL レコードを探します。
SELECT * FROM USER_MAPPING WHERE USERNAME IN (SELECT USERNAME FROM USER_MAPPING WHERE LOWER_USERNAME IS NULL);
これらのクエリが何らかの結果を返す場合、ソリューション 2 に進みます。
原因
このエラーは、データベースの重複した値か、ディレクトリのキャッシュの破損によって発生します。
ソリューション
ソリューション 1 user_mapping テーブルの重複レコード
Step 1: Review user_key
values of duplicated users
If the Diagnosis 1 query returns records, they'll look something like this:
user_key | username | lower_username |
---|---|---|
402881a340e4a73a0140e4a7e42c0009 | user1 | user1 |
402881a340e4a73a0140e4a7e42c0008 | user1 | user1 |
Step 2: Verify whether content is associated with user_key
取得した user_key のうち、作成済みのコンテンツを持たない user_key
を特定し、削除すべき重複ユーザーを特定します。返される count は 0 になります。
SELECT UM.USER_KEY FROM USER_MAPPING AS UM, CONTENT AS C
WHERE
(UM.USER_KEY = C.CREATOR OR
UM.USER_KEY = C.LASTMODIFIER)
AND C.CONTENTTYPE != 'USERINFO'
AND UM.USER_KEY IN ('<obtained_user_key1>','<obtained_user_key2>')
GROUP BY UM.USER_KEY;
Step 3: Delete user_key that isn't associated with any content
データベースの変更を行う場合は必ず事前にバックアップを取得してください。可能な場合は、まずステージング サーバーで SQL コマンドの変更、挿入、更新、または削除を行うようにします。
上述のクエリでカウントが 0 だったユーザーを削除します。重複エントリのみを削除し、0 以外の結果を持つアカウントは残すようにします。
DELETE FROM CONTENT WHERE CONTENTTYPE = 'USERINFO' and USERNAME = '<duplicated_user_key>';
DELETE FROM USER_MAPPING WHERE USER_KEY= '<duplicated_user_key>';
ソリューション 2 - user_mapping テーブルの NULL レコード
You are affected by the bug reported here: CONFSERVER-36018 - Duplicates in the People Directory due to duplicates in the user_mapping table. Follow the Workaround described in the ticket.