redo log 是事务持久性的保证
undo log 是事务原子性的保证
锁机制 是事务隔离性的保证
MySQL的自动加锁依赖于数据库的事务机制。当事务对某个数据行进行更新操作时,MySQL就会自动给该行加上排他锁,防止其他事务同时对其进行修改。同时,MySQL也会对读操作进行共享锁的加锁机制,确保读取的数据不被其他事务修改
MySQL的加锁机制是自动的,但人为干预也有其必要性。通过使用不同的加锁方式,可以灵活地掌控事务的并发控制,从而提高数据库的性能和安全性。
mysql 8.0 新特性
begin;
select * from table_name for share nowait 、 select * from table_name for share skip locked
表锁、页锁、行锁
myisam 存储引擎 只支持表锁
innodb 存在引擎 支持 表锁、页锁、行锁
查看锁的情况
show open tables ; # show open tables where in_use>0; 查看有锁的记录
lock tables 表 read ## 共享锁
lock tables 表 write ## 排它锁
unlock tables ## 解锁
意向锁 IX
自增锁 AUTO_INC 锁 表级别的
mysql 中 可以为某个列,加 Auto_increment 。
create table student(
stu_no int not null auto_increment,
stu_name varchar(20) not null
) engine = innodb default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
auto_increment 修饰的列,在添加数据的时候,可以省略或 null。
simple inserts 简单插入
可以**预先确定要插入的行数(当语句被初始化处理时)**的语句。包括没有嵌套子查询的单行和多行
insert 。。。。 values() 和 replace 语句
例如
insert into student(stu_name) values(‘zen’),(‘zen-ares’);
Bulk inserts 批量插入
**事先不知道要插入的行数(和所需要自动递增值的数量)**的语句。
insert 。。。。select ,replace。。。。select 和 load data 语句
innodb在处理一行,auto_increment 列分配一个新值
mixed-mode inserts 混合模式插入
innodb_autoinc_lock_mode
0:传统
1:连续
2:交错
元数据锁 MDL meta data lock
mdl锁,属于表锁范畴。MDL的作用是,保证读写的正确性。如果一个事务中一个查询正在遍历一个表的数据,而执行期间(事务没结束或终止)另一个线程(事务)对这个表结构做变更,增加一列,那么第一个事务的查询拿到的结构集跟表结构对不上,这个肯定是不行的。
对一个表做增删改查操作的时候,加 MDL读锁;当要对表做结构变更操作的时候,加MDL写锁
MDL读锁之间不互斥,因此可以多个线程(事务)同时对一个表增删改查。
MDL读写锁之间、mdl写锁之间是互斥的,用来保证变更表结构操作的安全性。
解决DML(如下)和DDL操作之间的一致性问题。不需要显示使用,跟意向锁一样,由引擎自动加解。
MDL在访问一个表的时候会被自动加上。
show processlist;
行锁 row lock 又称记录锁
封锁记录中的间隔,防止间隔中被其他事务插入。
间隙锁主要出现在RR隔离级别,避免出现幻读。
行锁分三类
Record Lock,记录锁,也就是仅仅把一条记录锁上;
Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象
Next-Key Lock:临键锁 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。
记录锁
当事务执行 commit 后,事务过程中生成的锁都会被释放。
Gap lock 间隙锁
Gap Lock 称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。
next lock 临键锁
next-key lock 即能保护该记录,又能阻止其他事务将新纪录插入到被保护记录前面的间隙中。 (a,b]
插入意向锁
一个事务在插入一条记录的时候,需要判断插入位置是否已被其他事务加了间隙锁(next-key lock 也包含间隙锁)。
如果有的话,插入操作就会发生阻塞,直到拥有间隙锁的那个事务提交为止(释放间隙锁的时刻),在此期间会生成一个插入意向锁,表明有事务想在某个区间插入新记录,但是现在处于等待状态。
页锁
悲观锁 乐观锁
隐式锁 VS 显示锁
查看锁情况
select * from performance_schema.data_lock_waits\G
显示锁
全局锁
死锁
产生死锁的必要条件
如何处理死锁
show variables like ‘innodb_lock_wait_timeout’;
锁结构
锁监控
show status like ‘%innodb_row_lock%’;
mysql 5.7
information_schema库中 innodb_trx 、innodb_locks 、 innodb_lock_waits 三个表中
innodb_locks :查看事务的锁情况,但只能看到阻塞事务的锁。
innodb_lock_waits: 只看等待的锁情况mysql 8.0
删除了 information_schema数据库中的 innodb_locks 添加了 performance_schema数据库中的data_locks 表
data_locks:可以看到阻塞的事务的锁,还可以看到该事务所持有的锁。
information_schema.innodb_lock_waits 替换成 performance_shcema.data_lock_waits
information_schema.innodb_trx 依旧保留
performance_schema.data_locks
select * from performance_schema.data_locks\G
information_schema.innodb_trx
select * from information_schema.innodb_trx\G