innodb锁

默认是行锁(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 cache
query_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的叶子节点。等同于表锁

posted on 2017-03-28 20:09  zhangshuo  阅读(909)  评论(0编辑  收藏  举报

导航