Mysql表锁行锁
读锁(共享性) 针对同一个数据,多个读操作可以同时进行并不受影响
写锁(排他性)当钱写操作没有完成前,它会阻断其他写和读
表锁
表锁偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定力度大,发生锁冲突的概率高,并发度最低
show open table # 查看哪些表被加锁了
分析表的锁定
show tatus like 'table%';
返回的table_locks_immediate表示可以立即获取锁查询的次数,每次立即获取了就++
Table_locks_waited 出现表级锁定征用而发生等待的次数,每等待一次锁值就++,如果值高就代表存在验证的表级锁征用的情况
为什么MyISAM不合适做写的主的表的引擎
Myisam读写的优先级是写优先,这也就导致了myisam不适合做写位主表的引擎。因为写锁后,其他线程不能做任何操作,大量的更新会导致查询很难得到锁,从而造成永久堵塞。
Mysql读锁
locak table A read # 设置读锁
比如session A对A表进行了加锁,它可以对A表进行查询,Session B也可以对A table查询
当前Session A可以查询该表的记录,其他session 也可以查询该表记录
当前session A不能查询其他没有锁定的表,其他session可以查询或者更新未锁定的表
当前Session A发起更新操作锁定的表都会报错, 其他session插入或者更新锁定的表会县城堵塞,一致等待获取锁。
总结:
在MyISAM引擎的表加读锁,不会堵塞其他线程对同一个表的读请求,但是会堵塞对同一个表的写请求,只有当读锁释放后还会执行其他进程的写操作。
Mysql写锁
lock tables A write # 设置写锁
Session A 对Table A设置了写锁
Seesion A可以对Table A进行增删改查操作,而seesion B对Table A查询会线程堵塞(如果查询到了就是从缓存查询出来的)
unlock tables # 释放锁
总结
在MyISAM引擎的表进行写操作,会堵塞其他进程对同一表的读和写操作,只有写锁释放了才会执行其他进程的读写操作
简而言之,就是读锁会堵塞写,写锁会导致读和写都被堵塞
行锁
行锁偏向InnoDB存储,开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率低,并发度也是最高的。
InnoDB与MyISAM最大的不同就是,支持事务,和行级锁
Mysql事务Transaction ACID
原子性(Atomicity)
事务是一个原子操作单元,对数据修改,那么全部执行要不全部不执行
一致性(Consistent)
在事务的开始和完成的时候都要保持数据的一致性。
隔离性(Isolation)
数据库提供的一种隔离机制,保证事务不受外部并发操作影响。线程之间的隔离
持久性(Durable)
事务完成后,他对数据的修改是永久的,即使出现系统故障也能保持持久性,修改后永久有效
并发会带来的问题会出现的问题
更新丢失lost update
当两个或者多个事务选择同一行,然后基于最初选定的值更新该行的时候,由于每个事务都不知道其他事务的存在,就会发生丢失更新的问题,最后的事务更新覆盖了其他事务所做的更新
脏读Drtry reads
事务A读取到了事务B已修改但是为提交的数据,还在这个数据基础上做了操作。此时如果事务B回滚了,事务A读取的数据无效,不符合一致性的要求。
脏读是事务A读到了事务B修改的数据
不可重复读Non-Repeatble Reads
一个事务读取某些数据后的某个时间,再去读取以前读过的数据,确发现其读出的数据已经发生了改变、或者某个记录已经被删除了,
事务A读取到了事务B已经提交修改的数据,不符合隔离性。
幻读
一个事务按相同的查询条件读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据.
事务A读取到了事务B提交的新增数据,不符合隔离性
幻读是事务A读到了事务B的新增数据
事务级别
隔离级别 | 脏 | 独 | 不可重复读 | 幻读 |
---|---|---|---|---|
未提交(Read uncommitted) | 只能保证不读取物理上的所怀数据 | 是 | 是 | 是 |
已提交度(read committed) | 语句级 | 否 | 是 | 是 |
可重复读(Repeatable read) | 事务级 | 否 | 否 | 是 |
可序列化(Serializable) | 最高级别,事务级 | 否 | 否 | 否 |
# 查看数据库事务的隔离级别
show variablees like 'tx_isolation'
数据库默认的隔离级别是可重复读,为什么不直接选择序列化是因为你并发作用越小,那么付出的代价也就越高,因为事务隔离实质上就是使用事务在一定程度上“串行化”进行,这显然与"并发"是矛盾的。同时,不同的应用对读一致性和事务隔离成都的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并没有那么敏感,这些业务可能更故安心并发访问的能力。
Mysql索引失效行锁变表锁
索引失效会导致行锁变成表锁
间隙锁的危害
当我们用范围条件的时候并请求共享锁或者排他锁的时候,InnoDB会给符合条件的已有数据几率的索引项加锁,对于键值在条件范围内不存在的记录也会被加锁,这就叫间隙锁(Next-Key)
它的危害就是会锁住一些不存在的键值,从而造成无辜的锁定。从而造成性能很大的危害
分析行锁
#通过检查innoDB_row_lock状态变量来分析系统上的行锁争夺情况
show status like 'innodb_row_lock%'
# innodb_row_lock_time_avg 平均等待时间
# innodb_row_lock_waits 等待总次数
# innodb_row_time 等待总时长
行锁的优化
尽可能让所有数据检索都通过索引完成,彼岸五索引行锁升级表锁
合理设计索引,尽量缩小锁的范围
尽量控制事务带下,减少锁定资源量和时间长度
尽可能低级别事务隔离
总结
InnoDB的存储引擎由于实现了行级锁定,虽然锁定机制的实现方面带来的性能消耗要比MyISAM高一些,但是整体并发处理能力要远远高于MyISAM的表级锁定,当系统并发较高的时候InnoDB的整体性能和MyISAM相比就会有比较明显的优势了。InnoDB如果使用不当的化,可能会让InnoDB的整体性能表现不如MyISAM,比如索引失效行锁变表锁