死锁是指两个或多个事务在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,这些事务都将无法继续执行下去。
在电商系统中,多个用户同时下单购买同一商品时,可能会发生死锁。
假设我们有两个事务同时插入数据到同一个表中:
-- 事务A
START TRANSACTION;
INSERT INTO orders (user_id, product_id, quantity) VALUES (1, 100, 2);
INSERT INTO order_details (order_id, product_id, quantity) VALUES (LAST_INSERT_ID(), 100, 2);
COMMIT;
-- 事务B
START TRANSACTION;
INSERT INTO orders (user_id, product_id, quantity) VALUES (2, 100, 1);
INSERT INTO order_details (order_id, product_id, quantity) VALUES (LAST_INSERT_ID(), 100, 1);
COMMIT;
为了避免死锁,可以按顺序加锁:
-- 事务A
START TRANSACTION;
LOCK TABLES orders WRITE, order_details WRITE;
INSERT INTO orders (user_id, product_id, quantity) VALUES (1, 100, 2);
INSERT INTO order_details (order_id, product_id, quantity) VALUES (LAST_INSERT_ID(), 100, 2);
UNLOCK TABLES;
COMMIT;
-- 事务B
START TRANSACTION;
LOCK TABLES orders WRITE, order_details WRITE;
INSERT INTO orders (user_id, product_id, quantity) VALUES (2, 100, 1);
INSERT INTO order_details (order_id, product_id, quantity) VALUES (LAST_INSERT_ID(), 100, 1);
UNLOCK TABLES;
COMMIT;
可以使用MySQL的SHOW ENGINE INNODB STATUS
命令来查看当前的死锁情况:
SHOW ENGINE INNODB STATUS;
死锁是并发系统中常见的问题,通过合理的事务设计和锁策略可以有效避免。在实际应用中,应根据具体业务场景选择合适的解决方案。
领取专属 10元无门槛券
手把手带您无忧上云