并发异常案例
一、并发读异常
DROP TABLE IF EXISTS `account_t`; CREATE TABLE `account_t` ( `id` INT(11) NOT NULL, `name` VARCHAR(255) DEFAULT NULL, `money` INT(11) DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_name` (`name`) )ENGINE = INNODB AUTO_INCREMENT=0 DEFAULT CHARSET = utf8; SELECT * from account_t; INSERT INTO `account_t` VALUES (1, 'C', 1000),(2, 'B', 1000),(3, 'A', 1000); -- 脏读读取了另一个事务未提交的修改 (其他事务的修改影响了本事务的读取) SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN -- 脏读事务1 UPDATE account_t SET money = money - 100 WHERE name = 'A'; -- 脏读事务2 -- SELECT money FROM account_t WHERE name = 'A'; -- SELECT money FROM account_t WHERE name = 'B'; -- 脏读事务1 UPDATE account_t SET money = money + 100 WHERE name = 'B'; -- 脏读事务1 COMMIT; -- 脏读事务2 -- COMMIT -- 不可重复读读取了另一个事务提交之后的修改(其他事务的修改影响了本事务的读取) SET TRANSACTION ISOLATION LEVEL READ COMMITTED; BEGIN -- 不可重复读事务2 -- SELECT money FROM account_t WHERE name = 'A'; -- 不可重复读事务1 UPDATE account_t SET money = money - 100 WHERE name = 'A'; -- 不可重复读事务1 COMMIT; -- 不可重复读事务2 -- SELECT money FROM account_t WHERE name = 'A'; -- COMMIT -- 幻读两次读取得到的结果集不一样 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN -- 幻读事务2 -- SELECT * FROM account_t WHERE id >= 2; -- 幻读事务1 INSERT INTO account_t(id,name,money) VALUES (4,'D',1000); -- 幻读事务1 COMMIT -- 幻读事务2 -- SELECT * FROM account_t WHERE id >= 2; -- COMMIT; -- 丢失更新(提交覆盖) SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN -- 丢失更新事务1 SELECT money FROM account_t WHERE name = 'A'; -- 丢失更新事务2 -- SELECT money FROM account_t WHERE name = 'A'; -- UPDATE account_t SET money = 1100 WHERE name = 'A'; -- COMMIT; -- 丢失更新事务1 UPDATE account_t SET money = 900 WHERE name = 'A'; COMMIT;
二、并发死锁
DROP TABLE IF EXISTS `account_t`; CREATE TABLE `account_t` ( `id` INT(11) NOT NULL, `name` VARCHAR(255) DEFAULT NULL, `money` INT(11) DEFAULT 0, PRIMARY KEY (`id`), KEY `idx_name` (`name`) )ENGINE = INNODB AUTO_INCREMENT=0 DEFAULT CHARSET = utf8; INSERT INTO `account_t` VALUES (1, 'C', 1000),(2, 'B', 1000),(3, 'A', 1000); -- 相反加锁顺序死锁1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN -- 死锁事务1 UPDATE FROM `account_t` SET `money` = `money` - 100 WHERE `id` = 1; -- 死锁事务2 -- UPDATE FROM `account_t` SET `money` = `money` - 100 WHERE `id` = 2; -- 死锁事务1 UPDATE FROM `account_t` SET `money` = `money` + 100 WHERE `id` = 2; -- 死锁事务2 -- UPDATE FROM `account_t` SET `money` = `money` - 100 WHERE `id` = 1; -- 相反加锁顺序死锁2 BEGIN -- 死锁事务1 UPDATE FROM `account_t` SET `money` = `money` + 100 WHERE `name` >= 'A'; -- 死锁事务2 -- DELETE FROM `account_t` WHERE `id` >= 1; -- 锁冲突死锁 BEGIN -- 死锁事务1 UPDATE FROM `account_t` SET `money` = `money` + 100 WHERE `name` = 'C'; -- 死锁事务2 -- UPDATE FROM `account_t` SET `money` = `money` + 100 WHERE `name` = 'A'; -- 死锁事务1 INSERT INTO `account_t` (`id`,`name`,`money`) VALUES (4, 'BB', 1000); -- 死锁事务2 -- INSERT INTO `account_t` (`id`,`name`,`money`) VALUES (5, 'CC', 1000);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现