默认是行锁(row lock)
InnoDB是通过在索引记录上加锁,实现行锁因此,没有索引时就无法实现行锁,而升级成全表记录锁,等同于表锁锁类型a、共享锁b、排他锁c、意向锁,InnoDB特有,加载在表级别上的锁
MDL
全局锁:
a,global read lock
b,query cache lock
mdl表锁
自增互斥量(mutex),用来管理Auto-increment
innoDB自旋锁,spinlock
system lock:文件系统级别锁,frm文件。
global read lock加锁:FTWRL,FLUSH TABLES WITH READ LOCK,
关闭实例下的所有表,并加上全局读锁,防止被修改,直到提交UNLOCK TABLES,
一般用于备份,mysqldump、xtrabackup都会发起,
xtrabackup时可分开备份InnoDB和MyISAM,或者不执行 -- master-data
query cache lock全局query cache锁,最好关闭
对QC中的数据有更新时,都会引发query cache lock
状态:Waiting for query cache lock
关闭query cachequery_cache_size = 0 & query_cache_type = 0
MDL,meta data lock,事务内的表级锁,
5.6.6前,事务开启后,会锁定表的meta data lock,其他会话对表有DDL操作时,均需等待mdl释放后方可继续
5.6.6后,不再阻塞其他会话执行DDL,但原来的会话再次访问数据表时,会有error提示:Table definition has changed, please retry transaction,
超时阈值定义:lock_wait_timeout
自增锁,其实是个轻量级的互斥量(MUTEX),相关选项 innodb_autoinc_lock_mode,
1 ,默认设置,可预判行数时使用新方式,不可预判时仍旧使用表锁,会造成autoinc列自增空洞,不过影响很小,
0 ,即沿用旧的表级锁模式,每次请求都会等待表锁,不过也非常快。不会影响整个事务,只影响当前的INSERT语句。
2 ,直接全部使用新方式,不安全,不适合replication环境
InnoDB spin lock,自旋锁,innodb_spin_wait_delay,控制轮训间隔,默认6秒,
show engine innodb status :
Mutex spin waits 5870888, rounds 19812448, OS waits 375285
事务并发非常高,CPU忙不过来的时候,事务处于sleep状态,spin round可能也会很高
获得mutex的过程:尝试获取mutex锁,如果已经被其他人锁定了,则会不断尝试:你的锁空出来了吗(这个过程叫做spin wait),多次尝试后,发现还是不行就放弃抵抗进入sleep状态,直到这个mutex 锁被释放了。
** Mutex spin waits 5870888,线程尝试获取spin锁而不可得的次数,也就是 spin-wait 的次数** rounds 19812448 ,线程进入spin wait循环的次数,也就是检查 mutex 锁的次数** OS waits 375285,线程放弃spip wait尝试,直接进入sleep状态的次数
innodb共享锁:
a,共享锁,不允许其他事物修改被锁定的行
b,select ... lock in share mode
c,或者是在事物中普通select
d,不在事物中的select是一致性非锁定读,不加锁。
InnoDB锁之排他锁,
对一行记录进行DML时,需至少加上排它锁,
锁范围视情况而定,可能是record lock、next-key lock,或者可能只有gap lock,
执行DML,或SELECT…FOR UPDATE,
innodb排它锁:
a,对一行记录进行DML时,需至少加上排它锁
b,锁范围视情况而定,可能是record lock、next-keylock,或者可能只有gap lock
执行DML.或select ...for update。
InnoDB锁之意向锁
IS,事务T想要获得表中某几行的共享锁IX,事务T想要获得表中某几行的排他锁
意向锁是加载在数据表B+树结构的根节点,也就是对整个表加意向锁,
意向锁的作用:避免在执行DML时,对表执行DDL操作,导致数据不一致
执行DDL,要扫描所有锁吧?如果加在聚集索引的根节点上就不需要扫描全表。意向锁加在btree根节点,
pt-osc:
先创建一样的表:create table like xx;
用触发器的方式将所有数据复制过来:create triggers,触发器的作用是保证数据更新同样搞过来。
最后把lock table,把表锁住,将最新数据拷贝过来。再改名,解锁。
无索引情况下,锁升级
全部 name = ? 的记录都会被锁定,对整张表的行记录加锁,next key lock 每个记录加一把锁,也就是btree的叶子节点。等同于表锁