想象一下,你走进了一个熙熙攘攘的舞厅,舞者们在快节奏的音乐下翩翩起舞,每个人都在寻找自己的舞伴和舞台。在数据库的世界里,这个舞厅就是我们的数据表,而舞者们则是那些并发的请求。MySQL的并发控制机制,就像是舞厅中的舞伴协调员,确保每个请求都能找到合适的舞伴,展现自己的优雅舞姿,而不会踩到别人的脚。
「MVCC」:通过保存数据的多个版本,允许读写操作并发执行,而不互相干扰。
「意向锁(Intention Lock)」:表明事务打算在表中的某些行上加锁。
BEGIN; SELECT * FROM tickets WHERE id = 100 FOR UPDATE; -- 若检查票尚未被预订,则进行预订操作 COMMIT;这里使用FOR UPDATE来加排他锁,保证了在事务完成前,其他事务无法修改这张票的信息。
「Undo Log」:当需要回滚时,用于恢复数据的旧版本。
-- 事务A BEGIN; SELECT COUNT(*) FROM users; -- 返回1000 -- 事务B同时插入新用户 INSERT INTO users (name) VALUES ('New User'); -- 事务A再次统计用户总数 SELECT COUNT(*) FROM users; -- 依然返回1000 COMMIT;由于MVCC的存在,事务A两次查询的结果一致,它没有看到事务B的插入操作,从而避免了幻读的问题。
-- 粉丝A抢购座位1 START TRANSACTION; SELECT * FROM concert_tickets WHERE seat_id = 1 FOR UPDATE; -- 粉丝B几乎同时抢购座位2 START TRANSACTION; SELECT * FROM concert_tickets WHERE seat_id = 2 FOR UPDATE; -- 粉丝A完成购买 UPDATE concert_tickets SET status = 'sold' WHERE seat_id = 1; COMMIT; -- 粉丝B也完成购买 UPDATE concert_tickets SET status = 'sold' WHERE seat_id = 2; COMMIT;由于每个座位是独立的行,行锁允许两个粉丝可以同时进行操作,而不会相互阻塞。
-- 管理员开始盘点,加表锁 LOCK TABLES books READ; -- 此时任何试图修改books表的操作都将会等待此锁释放 -- 例如,读者尝试借书 -- UPDATE books SET status = 'borrowed' WHERE id = 123; -- 此操作将被阻塞 -- 管理员完成盘点 UNLOCK TABLES;在管理员盘点过程中,读者的借阅操作将会被暂停,直到盘点结束,表锁被释放。
-- 活动策划者开始更新商品信息,加意向排他锁 START TRANSACTION; INSERT INTO intention_locks (table_name, lock_type) VALUES ('products', 'IX'); -- 此时,会计团队打算对所有商品进行价格核算,需要加表共享锁 -- 但因为存在意向排他锁,会计团队的操作需要等待 -- LOCK TABLES products READ; -- 此操作将被阻塞 -- 活动策划者完成商品信息更新 COMMIT; -- 意向锁释放后,会计团队可以加表共享锁进行核算 LOCK TABLES products READ;通过意向锁,数据库在事务之间建立了清晰的沟通,确保了锁的兼容性和协调性。