1.锁的概念
锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。
2.锁的分类
从对数据操作的粒度分 :
表锁:操作时,会锁定整个表。
行锁:操作时,会锁定当前操作行。
从对数据操作的类型分:
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(排它锁):当前操作没有完成之前,它会阻断其他写锁和读锁。
3.常用存储引擎对锁的支持
4. MyISAM表锁
显示加表锁语法:
加读锁 : lock table table_name read;
加写锁 : lock table table_name write;
总结:读锁会阻塞写,但是不会阻塞读;而写锁,既会阻塞读,又会阻塞写,所以MyISAM 的读写锁调度是写优先,因此 MyISAM 不适合做写为主的表的存储引擎。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。
5.Innodb行锁
行锁特点:偏向 InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB 与 MyISAM 的最大不同有两点:一是支持事务;二是采用了行级锁。
事务及其ACID属性:
并发事务处理带来的问题
事务隔离级别
innodb行锁模式
共享锁(S):又称为读锁,简称 S 锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
排他锁(X):又称为写锁,简称 X 锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
对于 UPDATE、DELETE 和 INSERT 语句,InnoDB会自动给涉及数据集加排他锁(X)
对于普通 SELECT 语句,InnoDB 不会加任何锁;
显式给记录集加共享锁或排他锁 :
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE
间隙(GAP)
当用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB 会给符合条件的已有数据进行加锁; 对于键值在条件范围内但并不存在的记录,叫做 "间隙(GAP)" , InnoDB 也会对这个 "间隙" 加锁,这种锁机制就是所谓的间隙锁(Next-Key 锁)
InnoDB 行锁争用情况
show status like 'innodb_row_lock%';
Innodb_row_lock_current_waits: 当前【正在等待锁定的数量】
Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg:【每次等待所花平均时长】
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间
Innodb_row_lock_waits: 【系统启动后到现在总共等待的次数】
SAM表锁