表结构
CREATE TABLE `payment` (
`id` bigint NOT NULL AUTO_INCREMENT,
`money` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO `payment`(`id`, `money`) VALUES (1, 5);
初始数据为id=1,money=5,实验开始,session1与session2执行相同的语句,但执行先后不同
show VARIABLES like 'autocommit';
show variables like '%transaction_isolation%';
set session transaction isolation level repeatable read;
set autocommit = 0;
start TRANSACTION;
SELECT money from payment where id = 1;
update payment set money = money+1 where id = 1;
SELECT money from payment where id = 1;
COMMIT;
执行如下操作:
- session1执行到l1,查看两次select结果,第一次是5,第二次是6,正常逻辑
- session2到l2处,会看到查询到了第一次执行结果5,语句阻塞在update(不要卡太久,执行第三步)
- session1执行l3,会看到session2的阻塞释放并返回第二次查询结果7
- session2执行l4
- session1,session2执行l5再次查看结果
结论:
- 在repeatable read级别事务并发时,对操作相同的记录会加锁
- 在repeatable read级别事务并发时,出现幻读
问题:
- 对操作相同的记录,相同如何定义:是主键索引、普通索引、普通字段?
- 加的什么锁
- 如何解决幻读
- 编程时容易出现的bug:将数据取出后在程序中运算再更新
- 若问题4中取出数据后要进行复杂的计算,或者需要联表呢,只能使用单纯的update更新,如何防止数据bug