Innodb
锁类型
共享锁(S)
排他锁(X)
意向共享锁(IS)
意向排他锁(IX)
X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible
Innodb的锁是作用于索引上的,因此理解innodb的锁,要先理解innode的索引实现B+树。
- 行级锁(Record Locks)
行级锁只存在于有索引的行上,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 锁住C1等于10的索引,此时不能在插入,修改或删除c1=10的行。
- 区间锁(Gap Locks)
区间锁是锁住两个索引的区间,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;加区间锁,锁住这个区间。则C1=15此时插入不进去。
- 间隙锁(next-key locks)
- 插入意向锁(Insert Intention Lock)
- 自增锁
自增锁是表锁。如果一个表有一个自增的列,则插入数据的时候,事务需要获得表锁。
Status报告
高并发关注点:SEMAPHORES
RW-shared是共享锁
RW-excl是排它锁
1 | ---------- |
- OS WAIT
reservation count表示Innodb产生了多少次OS WAIT, signal count表示,进行OS WAIT的线程,接收到多少次信号(singal)被唤醒。
如果你看到signal的数值很大,通常是几十万,上百万。就表明,可能是很多I/O的等待,或是Innodb争用(contention)问题。关于争用问题,可能与OS的进程调度有关,你可尝试减少innodb_thread_concurrency参数。
- Innodb如何处理互斥量(Mutexes)和两步获得锁(two-step approach)
首先进程,试图获得一个锁,如果此锁被它人占用。它就会执行所谓的spin wait,即所谓循环的查询”锁被释放了吗?”。如果在循环过程中,一直未得到锁释放的信息,则其转入OS WAIT,即所谓线程进入挂起(suspended)状态。直到锁被释放后,通过信号(singal)唤醒线程。
Mutex spin waits是线程无法获取锁,而进入的spin wait
rounds 是spin wait进行轮询检查Mutextes的次数
OS waits 是线程放弃spin-wait进入挂起状态
Spin wait的消耗远小于OS waits。Spinwait利用cpu的空闲时间,检查锁的状态,OS Wait会有所谓content switch,从CPU内核中换出当前执行线程以供其它线程使用。你可以通过innodb_sync_spin_loops参数来平衡spin wait和os wait。
LATEST DETECTED DEADLOCK
当你服务器发生了死锁的情况时,这部分会显示出来。死锁通常的原因很复杂,但是这一部分只会显示最后两个发生死锁的事务,尽管可能也有其它事务也包含在死锁过程中。
TRANSACTIONS
包含Innodb 事务(transactions)的统计信息,还有当前活动的事务列表。
参考链接
http://blog.51cto.com/louisyang/1379813
性能指标
TPS
TPS = (Com_commit + Com_rollback) / seconds
1 | show global status like 'Com_commit'; |
锁定状态
1 | show global status like '%lock%'; |
table_locks_immediate:表示可以立即获取锁的查询次数
table_locks_waited:表示不能立即获取锁的次数
Innodb_row_lock_current_waits:表示等待行锁定的数量,而与行数无关。
Innodb_row_lock_time:系统启动到现在,锁定的总时间长度
Innodb_row_lock_time_avg:每次平均锁定的时间
Innodb_row_lock_time_max:最长一次锁定时间
Innodb_row_lock_waits:系统启动到现在总共锁定的次数
问题:table_locks_immediate和 table_locks_waited,它们保持多大的比例是合适的?
table_locks_waited并不容易触发,除非应用主动作lock tables t read。
Table_locks_waited/Table_locks_immediate=0.3%,如果这个比值比较大的话,说明表锁造成的阻塞比较严重。
若库中都是InnoDB的表,在5.5以后,table_locks_waited这个值应该很小。在mysqldump导出表时,会执行lock table,可能导致此值增加。
其他情况下,若这个值有变,说明应用端主动作了lock table,这个在InnoDB表上是不需要的,需要应用修改。
锁事务
- 正在锁
1 | SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; |
- 等待锁
1 | SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; |
- 查看锁情况
1 | show status like '%lock%' |
Innodb_row_lock_current_waits 当前等待锁的数量
Innodb_row_lock_time 系统启动到现在,锁定的总时间长度
Innodb_row_lock_time_avg 每次平均锁定的时间
Innodb_row_lock_time_max 最长一次锁定时间
Innodb_row_lock_waits 系统启动到现在总共锁定的次数
区别是否锁表
- 当Table_locks_waited与Table_locks_immediate的比值较大,则说明我们的表锁造成的阻塞比较严重。
锁性能
InnoDB加锁的详细信息,主要用于分析一条语句的详细加锁结构以及加了什么锁。
1 | set GLOBAL innodb_status_output=ON; |
查看监控信息,Status字段的监控信息
1 | show engine innodb status; |
查看其中一条事务信息
1 | ---TRANSACTION 10701389, ACTIVE 0 sec |
参考链接:http://www.ywnds.com/?p=11750