matrixorigin / matrixorigin/matrixone
[Compatibility]: SAVEPOINT is accepted as a no-op while ROLLBACK TO remains unimplemented
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
### 问题描述
MatrixOne 的 MySQL 协议解析并接受 `SAVEPOINT` 和 `RELEASE SAVEPOINT`,但不会创建或释放任何保存点;`ROLLBACK TO SAVEPOINT` 始终返回未实现错误。因此应用会误以为保存点已建立,直到需要局部回滚时才发现功能不可用,保存点之后的修改仍可被整笔提交。
MySQL 使用保存点实现嵌套事务、ORM 局部回滚和一笔事务内的错误恢复。MatrixOne 当前行为与 MySQL 不兼容。
旧问题 #24736 已关闭;以下是在 latest main 上重新确认的当前行为,本 issue 不重开旧 issue。
### 环境
- MatrixOne latest `main`, commit `e7bb0572235ec4bac81eb098eb0ad8900f0065ab`
- MySQL 8.3.0(对照)
### 复现
```sql
create database savepoint_latest;
use savepoint_latest;
create table t(id int primary key,v varchar(20));
begin;
insert into t values(1,'before');
savepoint s1;
insert into t values(2,'after');
rollback to savepoint s1;
select * from t order by id;
release savepoint s1;
commit;
select * from t order by id;
```
### MatrixOne 行为
- `SAVEPOINT s1` 返回成功。
- `ROLLBACK TO SAVEPOINT s1` 返回:
```text
ERROR 20101: internal error: savepoint has not been implemented yet. please rollback the transaction.
```
- `RELEASE SAVEPOINT s1` 仍返回成功。
- 事务继续可用,`COMMIT` 后两行 `(1,'before')` 和 `(2,'after')` 均存在。
### MySQL 8.3.0 行为
`ROLLBACK TO SAVEPOINT s1` 删除保存点之后插入的第二行,同时保留第一行;`RELEASE` 和 `COMMIT` 成功,最终只存在 `(1,'before')`。
### 期望行为
MatrixOne 应完整实现 MySQL 保存点语义,包括:
- `SAVEPOINT name` 建立事务内回滚位置;同名保存点按 MySQL 规则替换;
- `ROLLBACK TO SAVEPOINT name` 回滚之后的写入但保持事务活动;
- `RELEASE SAVEPOINT name` 删除保存点,后续访问不存在的保存点应明确报错;
- COMMIT、完整 ROLLBACK 和隐式提交应清理所有保存点;
- prepared DML、唯一键/约束错误和多表修改后的局部回滚保持原子一致。
在功能实现前,至少不应让 `SAVEPOINT`/`RELEASE SAVEPOINT` 静默返回成功却不产生任何状态。
### 代码线索
`pkg/frontend/mysql_cmd_executor.go` 对 `SavePoint` 和 `ReleaseSavePoint` 直接返回 nil;`RollbackToSavePoint` 明确构造未实现错误。`pkg/sql/parsers/tree/stmt.go` 也将 Savepoint 标注为 Not Support。
Contributor guide
Assessment
This issue has not been assessed yet.