mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:37:34 +00:00
docs(advisory): position precision fix (#9882)
# Which Problems Are Solved We are deploying precision fixes on the `position` values of the eventstore. The fix itself might break systems that were already affected by the bug. # How the Problems Are Solved Add a technical advisory that explains background and steps to fix the Zitadel database when affected. # Additional Context - Original issue: [8671](https://github.com/zitadel/zitadel/issues/8671) - Follow-up issue: [8863](https://github.com/zitadel/zitadel/issues/8863) - Re-fix: https://github.com/zitadel/zitadel/pull/9881
This commit is contained in:
98
docs/docs/support/advisory/a10016.md
Normal file
98
docs/docs/support/advisory/a10016.md
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: Technical Advisory 10016
|
||||
---
|
||||
|
||||
## Date
|
||||
|
||||
Versions:[^1]
|
||||
|
||||
- v2.65.x: > v2.65.9
|
||||
|
||||
Date: 2025-05-14
|
||||
|
||||
Last updated: 2025-05-14
|
||||
|
||||
[^1]: The mentioned fix is being rolled out gradually on multiple patch releases of Zitadel. This advisory will be updated as we release these versions.
|
||||
|
||||
## Description
|
||||
|
||||
### Background
|
||||
|
||||
Zitadel uses a eventstore table as main source of truth for state changes.
|
||||
Projections are tables which provide alternative views of state, which are built using events.
|
||||
In order to know which events are reduced into projections, we use a `position` column in the eventstore and a dedicated table which records the current state.
|
||||
|
||||
### Problem
|
||||
|
||||
Zitadel prior to the listed version had a precision bug. The `position` column uses a fixed-point numeric type. In Zitadel's Go code we used a `float64`. In certain cases we noticed a precision loss when Zitadel updated the `current_states` table.
|
||||
|
||||
## Impact
|
||||
|
||||
During a past attempt to fix this, we got reports of failing projections inside Zitadel. Because the precision became exact certain compare operations like *equal*, *less then*, etc would now return different results. This was because the values in `current_states` would already have lost precision from a broken version. This might happen to **some** deployments or projections: there is only a small probability.
|
||||
|
||||
We are releasing the fix again and your system might get affected.
|
||||
|
||||
- Original issue: [8671](https://github.com/zitadel/zitadel/issues/8671)
|
||||
- Follow-up issue: [8863](https://github.com/zitadel/zitadel/issues/8863)
|
||||
|
||||
## Mitigation
|
||||
|
||||
When **after** deploying a fixed version and only when experiencing problems described by issue [8863](https://github.com/zitadel/zitadel/issues/8863), the following queries can be executed to fix `current_state` rows which have "broken" values. We recommend doing this in a transaction in order to double-check the affected rows, before committing the update.
|
||||
|
||||
```sql
|
||||
begin;
|
||||
|
||||
with
|
||||
broken as (
|
||||
select
|
||||
s.projection_name,
|
||||
s.instance_id,
|
||||
s.aggregate_id,
|
||||
s.aggregate_type,
|
||||
s.sequence,
|
||||
s."position" as old_position,
|
||||
e."position" as new_position
|
||||
from
|
||||
projections.current_states s
|
||||
join eventstore.events2 e on s.instance_id = e.instance_id
|
||||
and s.aggregate_id = e.aggregate_id
|
||||
and s.aggregate_type = e.aggregate_type
|
||||
and s.sequence = e.sequence
|
||||
and s."position" != e."position"
|
||||
where
|
||||
s."position" != 0
|
||||
and projection_name != 'projections.execution_handler'
|
||||
),fixed as (
|
||||
update projections.current_states s
|
||||
set
|
||||
"position" = b.new_position
|
||||
from
|
||||
broken b
|
||||
where
|
||||
s.instance_id = b.instance_id
|
||||
and s.projection_name = b.projection_name
|
||||
and s.aggregate_id = b.aggregate_id
|
||||
and s.aggregate_type = b.aggregate_type
|
||||
and s.sequence = b.sequence
|
||||
)
|
||||
select
|
||||
b.projection_name,
|
||||
b.instance_id,
|
||||
b.aggregate_id,
|
||||
b.aggregate_type,
|
||||
b.sequence,
|
||||
b.old_position,
|
||||
b.new_position
|
||||
from
|
||||
broken b;
|
||||
```
|
||||
|
||||
If the output from the above looks reasonable, for example not a huge difference between `old_position` and `new_position`, commit the transaction:
|
||||
|
||||
```sql
|
||||
commit;
|
||||
```
|
||||
|
||||
When there are no rows returned, your system was not affected by precision loss.
|
||||
|
||||
When there's unexpected output, use `rollback;` instead.
|
@@ -238,6 +238,18 @@ We understand that these advisories may include breaking changes, and we aim to
|
||||
<td>3.0.0</td>
|
||||
<td>2025-03-31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="./advisory/a10016">A-10016</a>
|
||||
</td>
|
||||
<td>Position precision fix</td>
|
||||
<td>Manual Intervention</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>2.65.10</td>
|
||||
<td>2025-05-14</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Subscribe to our Mailing List
|
||||
|
Reference in New Issue
Block a user