目录
锁是计算机协调多线程或进程并发的时候访问某一资源的机制。
这里的资源可以是cpu ram I/O ,也可以是数据库
通过锁来保证并发情况下,数据库数据的一致性、有效性
按照锁的粒度分为了以下三类
全局锁是对该数据库中的所有表加锁。
全局锁加锁后状态:所有表只读,dml、ddl语句都会阻塞
典型使用场景:数据库的备份
如下图(库存表、订单表、日志表):如果备份过程中,有其他进程访问表数据,就会造成备份的数据不一致的问题。
语法:
--加全局锁
flush tables with read lock;
--备份,注意这里是系统命令语句,不是mysql语句
mysqldump -uroot -p1234 itcast(数据库名)> D://itcast.sql(存储方式)
--释放全局锁
unlock tables;
--innodb引擎可以不加锁备份
mysqldump --single-transaction -uroot –p123456 itcast > itcast.sql
特点:
全局锁的操作比较重,严重影响效率。
主库上锁基本上业务停摆;从库上锁会造成主从延迟。
表级锁的粒度也较大,作用整张表,容易造成锁冲突,并发度低。
分类:
表共享读锁(read lock)
表独占写锁(write lock)
语法:
加锁:lock tables 表名 read/write;
释放锁:unlock tables/关闭客户端
锁住特点:
读锁:所有进程可读,所有进程不可写
写锁:当前上锁进程可读写,其余进程不可读写
这里的元数据,可以简单理解为就是一张表的表结构。 也就是说,某一张表涉及到未提交的事务时,是不能够修改这张表的表结构的。避免dml和ddl语句发生冲突。
元数据锁不用显示操作,mysql执行语句时自动加的。主要注意exclusive就是元数据的排他锁(写锁,修改元数据的时候加),平常增删改查的时候就是元数据共享锁。
查看元数据锁:
select object_type,object_schema,object_name,lock_type,lock_duration from
performance_schema.metadata_locks ;
加表锁的时候,需要每行遍历行锁,防止冲突,效率很低。innodb引入意向锁,来减少加表锁时的检查。
【意向锁,我的理解就是行锁在表级的一个标志,加表锁的时候需要查看意向锁,防止加的表锁和已经有的行锁冲突】
分类:
意向共享锁(IS) 与表共享读锁兼容,与表排他写锁互斥。
【我的理解是本质是行锁和 表锁的关系。行锁的读锁会和表读锁是兼容的,都允许读数据。行读锁和表写锁肯定互斥,读锁不允许写数据】。
意向排他锁(IX)与表读锁,写锁都互斥。
【我理解和上面一样,说明行锁是写锁,那自然不能再读写】
意向锁之间不会互斥。
【我的理解是因为操作的是不同行数据】
语法:
IS:select语句后面加 lock in share mode。
IX:增删改查语句后面加for update。
行级锁,锁的粒度最小,冲突概率最低,性能最好。
innodb的行级锁是索引项加锁实现的,而不是对记录加锁
sql语句自动加锁也和表锁那里一样:
insert/delete/update会自动加排他锁
select不会加锁,想要给select语句加锁可以在末尾写lock in share mode,for update
行锁是对单个行上锁。在RR,RC隔离级别下都支持。
行锁包括共享锁s 和排他锁x ,和表锁的共享读锁、独占写锁是一种分类
对同一行数据上锁时,冲突情况如下:
间隙锁是锁住索引间的间隙,防止别的事务插入,可以在RR隔离级别。
(这里和幻读的关系比较难理解,黑马上写的是防止幻读,但是有面经写过面试官说是错的,而且防止幻读和RR隔离级别会幻读相违背)。
正确的实验结果是:InnoDB在RR隔离级别下的幻读问题的分析_rr隔离级别存在幻读-CSDN博客
还会出现幻读的情况是因为:事务a的select语句不会自动加间隙锁,这时事务b插入数据就会出现幻读;但如果事务a的更改语句开始执行,间隙锁上锁,事务b就无法操作。
所以黑马和面试官都对,间隙锁确实可以防止幻读,但是select语句是不会加间隙锁的,正常操作时不会防止幻读。这也就与RR隔离级别会出现幻读相一致了。
冲突情况:
间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。
行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持
执行sql语句需要加锁时:
【就是说如果找18这个二级元素,会锁住所有18的数据,和18前后的间隙】
【就是范围里面的所有行和间隙加锁】
查询锁情况的语句:
select object_schema(库名),object_name(表名),index_name(索引),lock_type(锁的类型)
,lock_mode(锁的方式),lock_data(锁住的数据id)
from performance_schema.data_locks;