乐趣区

关于mysql:mysql的锁机制和mysql事务

mysql 锁机制

1).mysql 锁根底
锁期待景象
表级锁:锁住一张表的数据 =》myisam 下的,innodb 也可能有
页级锁:锁住一页的数据
行级锁:锁住一行的数据 =》innodb 下的
越往上,资源开销越小,然而越往上加锁速度越慢
锁抵触,表越往下的概率约低
并法度:行级锁并法度的概率最低

重点:innodb 下的行级锁

2). 排它锁与共享锁 - 重点:innodb 下的行级锁

排它锁加锁语法:select * from user where id=1 for update;

for update 示意对要查问的语句加排它锁

共享锁:select * from user where id=1 lock in share mode;

lock in share mode 示意加共享锁

set autocommit=0; 敞开事务主动提交配置 1 为主动提交,0 为勾销主动提交

排它锁:左边锁期待景象(排它锁与排它锁不能一起应用)

只有右边 commit 后能力查问进去

共享锁:就没有锁期待景象,两把共享锁能够同时应用

锁与锁之间的影响

事务与事务之间会不会有什么影响

排它锁与共享锁不能一起应用

事务 1 加排它锁,事务 2 加共享锁,事务 2 会进行锁期待

事务 1 加共享锁,事务 2 加排它锁,事务 2 会进行锁期待

对于 update, insert,alter 等写操作,mysql 在事务中会主动加上排它锁

select * from user where id=1; 对于一般查问,对锁没有影响,它仍然能够获取加锁后的数据

以后读取:加锁的 select 的查问
快照读取:没加锁的一般查问

写操作的一般 mysql 语句,其实在对于 innodb 会自带事务的开启以及提交(自带 begin,commit)
update user set username=‘111’where id=1;

锁机制:使咱们的业务强制进入串行化

3). 乐观锁与乐观锁的解释
乐观锁:不论是加什么锁,只有是上了锁都属于乐观锁(共享锁和排它锁都属于乐观锁)
乐观锁:乐观,不会加任何锁,比如说 MVCC

MVCC – 多版本的并发管制

软删除的意思
同例子:秒杀操作

以下哪些不是 mysql 的锁机制?排它锁

共享锁
表级锁
页级锁
行级锁
乐观锁
乐观锁

答案:乐观锁和乐观锁不是,他们属于概念,乐观锁是真的加锁,乐观锁是通过其余伎俩达到加锁的成果

4). 死锁的产生和解决:属于一个景象,两个事务都进入了锁期待景象
产生于两个或两个以上的过程当中
例子:事务 2 间接报错 Deadlock 退出,事务 1 批改胜利

还有一种景象:不会报错,然而会产生期待,事务 1 在期待事务 2,事务 2 在期待事务 1,锁等待时间超时还会报出异样
锁期待的工夫:wait_timeout=120 #设置的是锁期待的工夫
锁等待时间完结之后,事务会有一个失败和一个胜利
失败和胜利的 mysql 的抉择与事务的大小无关:select 比拟小,update 比拟大
个别准则:舍小保大
个别呈现死锁的范畴的:含糊查问,范畴查问

5). 间隙锁与行锁降级为表锁

间隙锁:当咱们应用的是范畴查问而不是等式查问,并申请或者排它锁的时候

危害:如果在查问中通过范畴去查问,锁住的范畴会是所有索引的键值。即便这个数据不存在

左边事务就进入了锁期待,因为右边事务中是间隙锁,包含了 id=3

行锁降级为表锁(只有 innodb 下产生)

锁去锁住的数据 =》是与索引有肯定的分割
?如何会产生?
主键与惟一索引 简直为 0
一般索引:很大几率会数据呈现反复
举例:此时事务 1 曾经降级到表锁了

在不加索引的字段上(除主键以及惟一索引之外)进行数据的加锁,会降级为表锁

如果字段在加了索引之后,就是该字段为一般索引,则加锁为行级锁

另外一个降级表锁状况:

因为是范畴查问 between,索引生效,所以降级为表锁

在加了索引之后,加锁会依据一般索引的根底下来进行加锁,而一旦索引生效,又会降级为表锁

防止降级表锁

1. 会尽可能是索引字段进行加锁
2. 尽可能应用等式而不是范畴性的查问

不只是排它锁,共享锁也是一样的情理

mysql 事务

1. 事务基础理论
应用领域:金钱交易,银行方面的业务,秒杀,订单生成

异样捕捉 try catch, 回滚
try{

select * from product where id=1 for update;
if(){
    echo“库存有余”;exit;
}
……
commit;

}catch(){

rollback;

}

事务的四大个性:
(1)原子性:要么全副执行胜利,要么全副执行失败 - 回滚日志
(2)一致性:在事务开始之前和完结之后, 数据都必须保 持统一状态, 必须保障数据库的完整性. 也就是说, 数据必须合乎数 据库的规定. 要求数据由一个状态转化为另一个状态 - 回滚日志
(3)持久性:保证数据不失落 - 通过重做日志
(4)隔离性:事务与事务之间不会相互影响 - 通过锁

发问:如果事务是手动开启,那么如何回滚数据,数据是否会主动回滚
答案:不会,只能通过手动执行 rollback

2. 事务通过锁实现隔离级别
每一个事物的开启,咱们能够把它看成一个盒子

事务的隔离级别:
读取未提交
读取已提交
可重读取(rr)
在可反复读中,该 sql 第一次读取到数据后,就将这些数据加锁(乐观锁),其它事务无奈批改这些数据,就能够实现可反复读了。但这种办法却无奈锁住 insert 的数据,所以当事务 A 先前读取了数据,或者批改了全副数据,事务 B 还是能够 insert 数据提交,这时事务 A 就会发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来防止。须要 Serializable 隔离级别,读用读锁,写用写锁,读锁和写锁互斥,这么做能够无效的防止幻读、不可反复读、脏读等问题,但会极大的升高数据库的并发能力。

串行化:只能排队读取

3. 事务的生命周期
原子性的实现
begin;
select * from user where id=1;
commit;
rollback

事务日志文件 =》重做日志 redo log=> ib_logfile0 从新执行

                    回滚日志 undo log=> ibdata      回滚数据

mysql 对于事物的执行 =》日志后行 但凡 sql 执行都会执行事务
日志优先级大于实际操作的数据的 所有执行的 sql 都会先执行日志,再写数据

BEGIN
update user set username=‘111’where id=1;
update user set username=‘111’where id=2;

2~3 步骤中:重做日志的会是缓存 而 回滚才是理论的(操作一次,记录一次)

4. 事务日志
事务的重做日志:事务的 id
show master status;

show binlog events in“mysql-bin.000003”\G;


提交 commit 时候会有 xid,就是事务 id
举例:
insert into user(id, username, age)values(1,’df’,10);
写入磁盘时候断电了呢?
在 mysql 事务执行了 commit 提交之后,服务器断电(挂了)然而数据还没有写入到磁盘中去,mysql 会在下一次重启时,依据重做日志写入数据到磁盘中去。

事务的回滚日志:事务 id,操作的数据元素,操作前的数据,操作后的数据
ROLLBACK
insert into user(id, username, age)values(1,’df’,10);
=>(回滚时会执行) delete from user where id=1; —记录一条相同的日志
执行:手动 ROLLBACK
在 mysql 事务没有执行 commit 提交,然而产生了异样,在下一次 mysql 重启服务的时候执行

回滚实现了事务的一致性和原子性
隔离性通过事务的锁来实现 =》行级锁
持久性 =〉通过事务的重做日志来实现

退出移动版