1. 表级锁和行级锁
表级锁(Table-level Lock)
表级锁是对整张表进行锁定,通常用于需要修改大量数据的操作。表级锁的优点是开销小,锁定快,但缺点是并发性能较差,因为一个表一旦被锁定,其他事务将无法同时对该表进行任何操作。
行级锁(Row-level Lock)
行级锁是对单行数据进行锁定,更适用于高并发操作。行级锁的优点是并发性能高,因为只锁定相关行,其他事务可以同时操作不同的行,但缺点是开销较大,锁定速度较慢。
InnoDB自动支持行级锁
START TRANSACTION;
UPDATE user SET age = 21 WHERE name = 'zhangsan';
COMMIT;
2. 排它锁和共享锁
排它锁(Exclusive Lock, X锁)
排它锁是对资源的独占访问,其他事务不能读或写被锁定的资源。常用于写操作(写锁)。
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- 对id=1的行加了排它锁,其他事务不能读取或修改这行数据
共享锁(Shared Lock, S锁)
共享锁允许多个事务同时读取资源,但不允许修改资源。常用于读操作(读锁)。
START TRANSACTION;
SELECT * FROM user WHERE name = 'zhangsan' LOCK IN SHARE MODE;
-- 事务期间对该行加上共享锁
COMMIT;
X和S锁之间有以下的关系: SS可以兼容的,XS、SX、XX之间是互斥的
一个事务对数据对象 O 加了 S 锁,可以对 O 进行读取操作但不能进行更新操作。加锁期间其它事 务能对O 加 S 锁但不能加 X 锁。
一个事务对数据对象 O 加了 X 锁,就可以对 O 进行读取和更新。加锁期间其它事务不能对 O 加任何锁。
3. InnoDB的锁机制
行级锁
1、InnoDB行锁是通过给索引上的索引项加锁来实现的,而不是给表的行记录加锁实现的,这就意味着 只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁。
2、由于InnoDB的行锁实现是针对索引字段添加的锁,不是针对行记录加的锁,因此虽然访问的是 InnoDB引擎下表的不同行,但是如果使用相同的索引字段作为过滤条件,依然会发生锁冲突,只能串 行进行,不能并发进行。
3、即使SQL中使用了索引,但是经过MySQL的优化器后,如果认为全表扫描比使用索引效率更高,此 时会放弃使用索引,因此也不会使用行锁,而是使用表锁,比如对一些很小的表,MySQL就不会去使用 索引。
InnoDB存储引擎默认使用行级锁,在WHERE条件下锁定符合条件的行。
START TRANSACTION;
SELECT * FROM user WHERE name = 'zhangsan' FOR UPDATE;
-- 事务期间对该行加上行级排它锁
COMMIT;
表级锁
InnoDB也支持表级锁,不过很少使用。
LOCK TABLES user WRITE;
-- 执行一些操作
UNLOCK TABLES;
4. MyISAM表级锁
MyISAM存储引擎只支持表级锁,不支持行级锁。
LOCK TABLES user WRITE;
-- 执行一些操作
UNLOCK TABLES;
5. 死锁
死锁是指两个或多个事务在同一资源上相互等待,导致无法继续执行。
START TRANSACTION;
UPDATE user SET age = 21 WHERE name = 'zhangsan';
-- 等待事务B释放锁
事务B:
START TRANSACTION;
UPDATE user SET age = 22 WHERE name = 'lisi';
-- 等待事务A释放锁
6. 锁的优化建议
- 尽量使用行级锁以提高并发性能。
- 确保事务执行时间尽可能短,避免长时间持有锁。
- 在设计表结构和索引时考虑锁的影响,尽量减少锁冲突。
- 使用合适的隔离级别以平衡并发性能和数据一致性。
7. MVCC(多版本并发控制)
MVCC是一种并发控制机制,通过保存数据的多个版本来实现并发访问,避免加锁。InnoDB使用MVCC来实现可重复读和已提交读隔离级别。
-- 在可重复读隔离级别下执行
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM user WHERE name = 'zhangsan';
-- 此时即使其他事务修改了这行数据,也不会影响当前事务的读取结果
COMMIT;
总结
MySQL的锁机制是确保数据一致性和提高并发性能的关键。了解和合理使用表级锁、行级锁、排它锁、共享锁,以及InnoDB和MyISAM存储引擎的锁机制,可以有效地优化数据库操作。通过避免死锁和利用MVCC,可以进一步提升系统的稳定性和性能。