简短结论:Cursor(游标)本身不一定会阻塞,但它“用得不对”非常容易造成阻塞和性能问题。是否阻塞,取决于数据库类型、隔离级别、游标类型、是否加锁、以及事务是否长时间不提交。
下面分场景说清楚。
这是最常见的原因。
例如在 SQL Server / Oracle / PostgreSQL 中:
BEGIN TRANSACTION;
DECLARE cursor_name CURSOR FOR
SELECT * FROM orders WITH (UPDLOCK);
OPEN cursor_name;
-- 慢慢处理,几分钟不提交
➡ 游标持有的锁不会释放 ➡ 其他会话更新/读取相关行时被阻塞
✅ 阻塞来源不是“游标”,而是“未提交的事务 + 锁”
DECLARE cur CURSOR FOR
SELECT * FROM user WITH (UPDLOCK)
或 PostgreSQL:
DECLARE cur CURSOR FOR
SELECT * FROM user FOR UPDATE;
➡ 会逐行加锁 ➡ 其他事务修改这些行时会被阻塞
以 SQL Server 为例:
如果游标是 DYNAMIC,并且事务很长: ➡ 会持续占用锁资源
DECLARE cur CURSOR FOR
SELECT id FROM table;
并且:
FOR UPDATE➡ 基本不会阻塞
例如 Python:
cursor.execute("SELECT * FROM table")
for row in cursor:
...
| 数据库 | 游标是否容易阻塞 | 说明 |
|---|---|---|
| SQL Server | ⚠ 容易 | 取决于游标类型 + 事务 |
| Oracle | ⚠ 中等 | 默认读一致,更新游标会锁 |
| PostgreSQL | ⚠ 中等 | FOR UPDATE 会锁 |
| MySQL | ✅ 较少 | 本质多为结果集 |
UPDATE table SET status = 1 WHERE status = 0;
比逐行游标快且安全。
READ ONLYFAST_FORWARD(SQL Server)FOR UPDATEWHILE ...
BEGIN
-- 处理 100 行
COMMIT;
END
游标 ≠ 阻塞 长事务 + 锁 = 阻塞
Cursor 本身不“必然”阻塞,但游标 + 锁 + 长事务 = 阻塞高危组合。
如果你愿意,可以告诉我:
我可以直接帮你判断“你这个游标会不会阻塞”。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。