一、MySQL示例
-- 查看将要更新的记录
SELECT id, age FROM person WHERE id IN (1, 2)
-- 开始事务
BEGIN;
UPDATE person SET age = 20 WHERE id IN (1, 2)
-- 执行完成之后直接查看数据会发现数据还没更改,需要后续执行提交或回滚才会生效
-- 检查更新结果
SELECT ROW_COUNT(); -- 查看影响的行数
-- 观察控制台输出行数,如果确认更新是否正确,在选择执行提交或回滚
-- COMMIT;
-- ROLLBACK;二、postgreSQL示例
--开启手动提交事务
BEGIN;
-- 要批量更改的内容
UPDATE person SET age = 20 WHERE id IN (1, 2)
-- 观察控制台输出行数,如果行数确认,则提交事务
-- COMMIT;
-- 观察控制台输出行数,如果行数不对,则提交回滚事务
-- ROLLBACK;三、注意问题
在 MySQL(特别是 InnoDB 引擎)中,长时间不提交事务同样会带来严重问题:它会持续持有行级锁和可能的间隙锁,阻塞其他事务对相同数据的修改操作,导致系统出现锁等待超时和连锁阻塞;同时会占用大量的回滚段空间来保存旧数据镜像,可能耗尽 Undo 表空间,导致新的写操作失败。虽然不像 PostgreSQL 有事务ID环绕的风险,但会严重影响数据库并发性能和系统稳定性,因此也必须立即提交或回滚挂起的事务。
在 PostgreSQL 中,长时间不提交事务会带来严重后果:它会持续锁定更新的数据行,阻塞其他会话的写操作,引发性能下降和连锁阻塞;同时会阻止系统的自动清理机制,导致表空间膨胀和查询性能恶化。最危险的是可能引发"事务ID环绕"问题,当事务年龄接近20亿时,数据库会进入紧急只读模式,需要复杂的恢复操作。因此,必须立即对挂起的事务执行 COMMIT 或 ROLLBACK 操作,避免对整个数据库系统造成严重影响。
四、注意问题对应的解决方案
postgreSQL
立即决定:COMMIT; 或 ROLLBACK;
强制终止:SELECT pg_terminate_backend(pid);
预防设置:配置 statement_timeout、lock_timeout
MySQL
立即决定: COMMIT; 或 ROLLBACK;
强制终止: KILL [session_id];(使用 SHOW PROCESSLIST; 先查询会话ID)
预防设置:
配置 innodb_lock_wait_timeout(锁等待超时)
配置 wait_timeout 和 interactive_timeout(连接空闲超时)
启用 innodb_rollback_on_timeout(超时自动回滚)