(1)锁的概述
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU, RAM, I/0)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
MySQL中的锁,按照锁的粒度分,分为以下三类:
-
全局锁:锁定数据库中的所有表。
-
表级锁:每次操作锁住整张表。
-
行级锁:每次操作锁住对应的行数据。
(2)全局锁
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
加全局锁
flush tables with read lock;
加了全局锁之后,只能查不能写;
释放锁
unlock tables;
数据库中加全局锁,是一个比较重的操作,存在以下问题:
1)如果在主库上备份,那么在备份期间都不能 执行更新,业务基本上就得停摆。
2)如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。
在InnoDB引擎中,我们可以在备份时加上参数 --single-transaction参数来完成不加锁的一致性数据备份。
mysqldump --single-transaction -uroot -p123456 xxxx>xxxx.sql
(3)表级锁
表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。
对于表级锁,主要分为以下三类:
(1)表锁
1)表共享读锁(read lock)
2)表独占写锁(write lock)
加锁: lock tables xxx read/write
释放锁: unlock tables / 客户端断开连接
lock table score read;
加读锁之后,可以正常select * from score, 进行表数据的读取。

其他客户端也可以进行正常的读取

加读锁之后,无法对表进行update、insert等操作
update score set math=100 where id=2; 报错 table 'score' was locked with a read lock and can't be updated;

其他客户端进行update、insert操作时,会被阻塞,直到读锁被解除.


客户端对表加了写锁之后, 当前客户端可以对表进行写和读; 其他客户端不能对表进行写和读.
其他客户端对这张表进行读取时,会一直堵塞; 对表进行写时,也会一直堵塞, 直到锁释放为主.


(2)元数据锁(meta data locak, MDL)
MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上. MDL锁主要作用是维护表元数据的数据一致性, 在表上有活动事务的时候,不可以对元数据进行写入操作.

当对表进行select, insert, update, delete, select ... for update时, MDL加的是shared_read, shared_write锁; 而alter table操作时,MDL锁类型时exclusive;
shared_read, shared_write与exclusive是相互互斥的.

可以通过select object_type, object_schema, object_name,lock_type, lock_duration from performance_schema.metadata_locks; 查询MDL锁

(3)意向锁
为了避免DML在执行时, 加的行锁与表锁的冲突, 在InnoDB中引入了意向锁, 使得表锁不用检查每行数据是否加锁, 使用意向锁来减少表锁的检查.
意向锁分为:
(1) 意向共享锁(IS): 右语句select ... lock in share mode添加; 与表锁共享锁(read)兼容, 与表锁排它锁(write)互斥.
(2) 意向排它锁(IX): 由insert, update, delete, select ... for update添加. 与表锁共享锁(read)及排它锁(write)都互斥. 意向锁之间不会互斥.
可以通过以下sql, 查看意向锁及行锁的加锁情况
select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks
通过select * from score where id = 1 lock in share mode; 进行添加意向锁

意向共享锁, 可以和表的读锁共享,不互斥
