以前在上文已经记录过锁的简单应用今天更深刻的了解一下MySQL中的锁。php
锁类型 | 存储引擎 | 特色 |
---|---|---|
表级锁 | MyISAM、MEMORY、InnoDB(非默认) | 开销小,加锁快,不会死锁,颗粒大,并发低。 |
行级锁 | InnoDB | 开销大,加锁慢,会死锁,颗粒小,并发高。 |
页面锁 | BDB | 介于以上两种之间,会死锁。 |
表级锁支持两种模式,共享读锁和独占写锁。sql
READ锁定后,当前线程不能够写入,其余线程写入会被阻塞到解锁后执行,查询不受影响。并发
WRITE锁定后,当前线程能够插入查询,其余进行插入查询会被阻塞到解锁后执行。spa
查看表等待数量.net
//查看表等待次数 show status like 'table%';
通常会体如今 table_locks_waited中,若是比较高说明发生大量锁等待。线程
MySQL执行读写操做会自动进行锁定,通常不须要显示指定。code
锁的使用方法能够参考:锁的简单应用blog
LOCK TABLES table_name READ LOCAL;
LOCAL表示容许获取读锁的时候在表结尾进行并发插入。索引
MySQL能够经过 concurrent_insert 来控制并发插入。进程
concurrent_insert 为 0 的时候不容许并发插入。
concurrent_insert 为1 的时候,若是表中不存在空洞能够在结尾插入。
concurrent_insert 为 2 的时候,是否有空洞都容许结尾插入。
若是加锁的时候已经被其余线程锁定,则会阻塞到其余线程解锁。
若是两个进程同时进行读锁和写锁的请求,那么写锁会优先执行,哪怕读锁先到。
咱们能够经过 low-priorty-updates 参数来设置优先级别。
SET LOW_PRIORITY_UPDATES=1; SET LOW_PRIORITY_INSERT=1; SET LOW_PRIORITY_DELETE=1;
经过设置来下降写的优先级。
同时还能够经过设置 max_write_lock_count 来实现锁等待超过必定数量后读优先,用于避免大量写操做致使查询阻塞。
事务做为一个单独的处理单元具备原子性,要么所有执行,要么所有不执行
事务的开始和结束都保持一致状态,事务结束的时候必须保证数据是正确的。
并发事务的状况下,不容许互相影响,每一个事务必须是隔离开的。
事务一旦提交便永久生效。
两个并发事务A和B,A和B同时读取了数据,A修改数据提交后,B页修改数据进行提交,会覆盖A种修改的数据。
两个并发事务A和B,A读取并修改了数据可是没有提交,B此时读取了A修改后的数据并提交,此时A回滚了数据,那么B提交的数据会成为脏数据。
一个事务读取数据后,再次读取数据(同一条数据)发现两次数据不一致。
一个事务读取数据后,再次读取数据(相同条件读取的数据),发现其余事务插入了知足条件的新数据。
经过排他锁避免更新丢失。
这个级别的事务能够读取到其余事务的未提交数据,因此会产生脏读。
经过排他锁和共享空间锁来避免更新丢失和脏读。
这个级别的事务能够读取到其余事务已经提交的数据,因此屡次读取会出现“不可重复读”。
经过排他锁和共享空间锁来避免更新丢失和脏读,在进行读锁的时候禁止写锁执行,写锁的时候禁止任何锁执行,用于避免重复读。
最为严格的隔离机制,经过串行的方式保证事务一个一个执行。
//查看隔离级别 select @@global.tx_isolation,@@tx_isolation;
show status like 'innodb_row_lock%';
经过查看返回结果中 锁等待次数和平均等待时间来判断当前锁情况,若是比较高说明当前锁竞争严重,能够经过查看 schema.innodb_locks来进一步查询。
共享锁(S):对一行数据开启共享锁,会阻止其余数据对这行数据开启排他锁。
排他锁(X):得到排他锁的数据能够写数据,其余数据不能够得到共享锁或排他锁。
为了兼容表级锁,实现了如下两种锁。
意向共享锁(IS):事务获得共享锁以前先取得该锁。
意向排他锁(IX):事务获得排他锁以前先取得该锁。
InnoDB种不须要显式的加锁,会在执行语句时候自动加锁解锁。
InnoDB行锁经过给索引上的索引项加锁,没有索引会加载汇集索引上。
一、Record lock:直接对索引项加锁
二、Gap lock:对索引项第一条和最后一条的位置加锁(GAP锁)用于防止幻读(RC、RR隔离级别)。
三、Next-key lock:二者结合
InnoDB加锁若是使用索引(非主键),会同时给索引项和汇集索引项加锁。
范围查询的时候会锁住范围内的全部索引项。
注意:若是检索数据没有经过索引条件检索(全表扫描),那么将对表中全部数据加锁。