数据库锁机制简单来说,就是数据库为了保证数据的一致性,使各种共享资源
在被并发访问时变得有序而设计的一种规则。
mysql的锁机制比较简单,最显著的特点是不同的存储引擎支持不同的锁机制。
我们所知道,innoDB 支持行锁,有时也会升级为表所,myisam 只支持表锁
表锁:开销小,加锁快,不会出现死锁现象,锁的粒度大,发生锁冲突的概率高
并发支持较低
行锁:开销大,加锁慢,会出现死锁,锁的粒度小,发生锁冲突的概率低,并发支
持较高;
innoDB锁的类型
1)读锁
类似多线程中的读写锁的读锁 一个事务获取到读锁之后,别的事务也可以获取该
读锁,但是不能获取到写锁
2)写锁
类似多线程中的读写锁的写锁 一个事务获得写锁之后 其他的事务不能获取读锁和
写锁
3)意向锁
意向锁是表级锁 分为意向共享锁(需要先获取读锁) 和意向排他锁(需要先获取写锁)
它的作用和MDL锁类似,都是防止在事务进行中,执行DDL语句的操作致使数据的不一致
4)MDL锁
事务开启之后会自动获取MDL 锁, 另外一个事务就不能执行DDL 语句操作
即不能修改表的结构, 它用于保证表中元数据的信息
innoDB行锁种类
1)单个行记录的锁
是加载索引项上面的, 当同时操作同一条数据的时候,会出现锁竞争和等待
现象, 主键索引和唯一索引,都是使用的单个行记录锁,同时RC(读已提交)
离级别,只有行记录锁。
2)间隙锁
在RR(可重复读)隔离级别中,为了避免出现幻读,就使用了间隙锁,他是一个
范围锁,假如 查询score<90 的记录,那么这个范围内的所有数据都不能执行数据
的修改操作。 注意:RC(读已提交)隔离级别的情况下 间隙锁不起作用。
3)记录锁和间隙锁的组合叫做 next-key lock
当innoDB扫描索引索引记录时,会先对选中的索引记录加上记录锁,然后再
对索引两边的间隙加上间隙锁。
如score<80 的范围 ,同时也会再80加上锁
死锁
类似多线程死锁现象。
上述例子 都是使用begin开启了事务 而没有使用commit 提交或者rollback回滚事务。
生产环境中如何避免死锁现象的产生
1)如果多个不同的程序会并发 存取多个表,或者涉及到多行记录时,尽量约定以相同的顺序访问表,可以大大降低死锁的现象。
2)业务中尽量使用小事务,避免使用大事务,要及时提交或者回滚事务,可以减少死锁现象的产生频率。
3)在同一个事务中,尽可能做到一次锁定所需要的所有的资源,减少死锁产生的概率。
4)相对于非常容易产生死锁的业务部分,可以尝试升级锁的粒度,使用表锁,来避免死锁现象的产生。
锁的监控
通常情况下,当出现锁的问题时,我们习惯性通过show full processlist 和show engine innodb status 命令来判断事务中锁问题出现的情况。其实还有三张特殊的表。即在 infomation_schema 库下的 INNODB_TRX 、INNODB_LOCKS、INNODB_LOCK_WITS。 这三张表可以更方便的来帮助我们监控当前的事务,并分析可能存在的锁问题。
主要字段的介绍
trx_id :唯一的事务id
trx_state:当前事务的状态, lock wait 和running
trx_wait_started:事务的开始时间
trx_qurery:事务运行的sql语句
trx_operation_state:事务的运行状态
还可以通过查看INNODB_LOCKS 和INNODB_LOCK_WAITS两张表 来查看 持有锁和锁等待的现象。