一直潜行在钻研自动化测试领域技术,一发不可收拾,差不多快把MySQL的知识忘光了。
为了巩固自己学的MySQL知识,数据库理论,也该是时候yy一下,通过巧妙的架构设计,让MySQL的性能级别达到银行级别的强一致性,主从零延迟、24小时前端业务零故障,健壮的异地灾备。分钟级的数据恢复,无限自动扩容。这也是DBA专家级别的水平所具备的,有喜欢数据存储架构的同学,无论是其他数据库,还是整体数据架构,向这个方向发展,你就是业界最牛的架构师!
最近看到好多DBA群里,很多人在问。
问题列表:
1、 xxx行数据,什么情况下锁表or不锁表、
2、什么情况下走索引or不走索引、
下面我们从原理开始讲起。这是why 傻么乐?
1、 解答,数据库称之为数据库的本质原因是它有加锁机制,从而实现了事务的隔离性。
从测试角度来看,程序在什么时候容易出问题,答案就是:“高并发下的事务操作”。这里稍微解释一下,高并发说明同一时间有大量用户操作应用导致同一时间应用频繁访问数据库,数据库为了并发安全,去频繁的加锁保证事务的隔离性,然后就降低了数据库性能,甚至会出现用户读到的数据不一致等。事务隔离级别我们DBA是可以设置的,为了权衡利弊,这里面我们把事务隔离级别设置为RR(可重复阅读) 这个也是数据库默认的隔离级别,一般情况下,不需要手工改动它,它唯一出现的问题就是:产生幻读,
“幻读”:简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。所以啊,用低版本的MySQL,和使用其他存储引擎的时候,还是会出现幻读的,请小心哦~
现在基本都是在用MySQL默认的InnoDB存储引擎了。这种存储引擎呢,就只有两种类型的锁:表锁、行锁,!
我们在看看这两种类型锁的有优缺点:
表锁:开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
行锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高
所以啊正常的高并发事务处理,要避免产生表锁,使用行锁的时候,尽量避免死锁哈!
我们先看看表锁下有几种加锁模式,这里我就不区分表锁和行级锁各种名词了“共享(s),排他(x),还是意向的(这个是mysql自动完成的,不用搭理她)”我们统一叫,读锁,写锁!如果想看专业名词,可以看看我之前写过的博客:
https://www.ztloo.com/2017/05/16/day23-mysql的锁详解/
当一个表或数据行被加了读锁,其他进程仍可以对其加读锁,可是不能加写锁,当一个表或数据行被加了写锁,其他进程不能对其加读写锁。
应该不哟用我解释问题1了吧,我觉得大家可以理解,什么时应该锁表了吧,什么时候会产生等待锁释放吧。
问题2,没走索引,那是没有充分了解mysql不走索引的约束规则:
使用函数运算了,使用负向查询,join两边类型字段类型不一致 ,以%开头,带有or,字符串没有带引号,复合索引不满足最左前缀,使用了表达式。
虽然说MySQL57 版本已经支持所谓的索引函数,但是小编还没看到哪家花联网公司敢应用哈~,
这里建议只让数据库做高并发的事务读取,修改就可以了。计算还是留给程序端来处理吧!
发生死锁的原因:加锁顺序不一致!
防止死锁的建议:
把大事务让它分解成一个个小事务,原因是锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放。要避免表被长时间锁定,就要避免大事务!
合理使用索引,是让锁定、扫描的范围变小,不会影响其他并发读写锁的事务操作。
a)类似业务模块中,尽可能按照相同的访问顺序来访问,防止产生死锁;
b)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率。
c)对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率。
什么情况下锁表,什么情况下不锁表,这个不是DBA还是开发臆测出来的,这个是产品根据业务的要求必须用应用程序进行严格的事务控制的!
DBA呢只要通 检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况就可以了!
行锁里面还细分三个锁策略:下面的3是默认策略。
1,Record Lock:单个行记录上的锁。
2,Gap Lock:间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。
3,Next-Key Lock:1+2,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。
这里重点说一下:
间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间
innodb自动使用间隙锁的条件:
(1)必须在RR级别下
(2)检索条件必须有索引
容易产生的问题:当插入间隙部分的数据范围时候,会产生sql阻塞异常报错。
Next-Key Lock
在默认情况下,mysql的事务隔离级别是可重复读,并且innodb_locks_unsafe_for_binlog参数为0,这时默认采用next-key locks。所谓Next-Key Locks,就是Record lock和gap lock的结合,即除了锁住记录本身,还要再锁住索引之间的间隙。
~~~~~~~~结束了~~~~~~~