文章目录
数据库事务:
- 针对数据库的某一组操作要么全部成功,要么全部失败。
事务的作用
1:保证数据的完整性,失败后可以恢复到原来状态
2:事务与事务之间互不干扰,这样数据会更加安全
数据库事务ACID属性 / 特性
原子性(Atomicity):要么全部完成,要么全部不完成。
一致性(Consistency):事务必须始终保持系统处于一致性。
隔离性(Isolation):隔离执行事务,使它们好像是系统在给定时间内执行的唯一操作。
持久性(Durability):事务完成后,该事务对数据库的更改持久保存在数据库中。
事务的隔离性
对于同时运行的多个事务,当这些事物访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。
不可重复读:一个事务T1读事务T2的数据,多次内数据不一样。
幻读:事务T1对自己某一项的数据全部修改后T2又对数据进行修改,T1在读后发现有一条不一样。
脏读:一个事务T1已经读到了事务T2未提交的数据,如果T2事务不提交,那么T1再次读到的数据跟前一次不一样。
数据库事务隔离级别
Mysql四种,Mysql默认Repeatable read.
Oracle两种(Read Commited,Serializable)Oracle默认Read committed。
事务隔离
READ UNCOMMITTED:使用查询语句不会加锁,可能读取未提交的行。
READ COMMITTED:只对记录加记录锁,不会在记录之间加间隙锁,允许新的记录插入到被锁记录的附近,多次使用查询语句时,可能得到不同的结果。
REPEATABLE READ:多次读取同一范围的数据会返回第一次查询的快照,不会返回不同的数据行,可能发生幻读。
SERIALIZABLE:InnoDB隐式地将全部的查询语句加上共享锁,解决幻读的问题。
隔离级别的语法
1:查看
select @@tx_isolation;
2:设置
set transaction isolation leval 级别;
3:jdbc设置隔离级别
connection.setTransactionIsolation(1|2|4|8);
数据库的隔离级别导致的问题
脏读
一个事务对数据进行了修改,但未提交,另一个事务可以读取到未提交的数据。如果第一个事务回滚了,第二个事务读到的了脏数据。
不可重复读
一个事务中发生了两次读操作,第一次读操作和第二次读操作时间,另外一个数据对数据进行了修改,这时候两次读取的数据不一致。
幻读
第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围内增加了一条数据,这时候第一个事务就会丢失对新增数据的修改。
数据库事务的基本使用
mysql--> dbms-->数据库事务自动提交
一个crud事务就是一个事务,当有一个操作是会自动提交事务,提交后的数据持久改变,
刻入磁盘,当发生异常,设置回滚,数据库就不会有所改变
没有异常 commit
抛出异常 rollback
在MySQL数据库中查看当前事务的隔离级别:
select @@tx_isolation;
在MySQL数据库中设置事务的隔离级别:
set [glogal | session] transaction isolation level 隔离级别名称;
set tx_isolation=’隔离级别名称;’
mysql的事务死锁
锁:
锁并不是和事务绑定一起的,不同的语句可能锁集不同,但是事务的隔离级别会影响锁的范围.
不在事务当中的UPDATE,INSERT等也都会用到锁.
锁的范围
1.record lock:记录锁
当我们加入select * from orders whereid = 1 for update这样会阻止其他语句增删改这条数据.
2.gap lock:间隙锁
间隙锁,这个锁会锁住该数据上一个邻近位置(根据索引或者主键)与下一个邻近位置之间的范围.(对于索引而言)
锁住区间范围(邻近的index-1,index);
3.next-key lock:gap lock + recordlock
事务级别最低为repeatable read,会启用这个锁,如果低于这个级别会不起用这个锁.
因此锁的范围就变为了(邻近的index-1,index];
REPEATABLE READ下的加锁规则
原则 1:加锁的基本单位是 next-key lock。希望你还记得,next-key lock 是前开后闭区间。
原则 2:查找过程中访问到的对象才会加锁。
优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,nextkeylock 退化为间隙锁。
一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止
死锁
死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待.
等待图(wait-for-graph)可以用来检测死锁,通过深度优先算法实现,只要图中存在循环的回路.那么存在死锁.
解决死锁时会回滚当中undo量最小的一个事务。
意向锁
意向锁是表级锁,指明事务在将要对表中的行加哪种意向锁.
IS:指明事务将会在表中的行加共享锁.
IX:指明事务将会在表中的行加排它锁.
意向锁的意义:表明某个事务正在锁或者将要锁表中的一行数据.
意向锁不会阻塞除全表操作以外的(例如:LOCK TABLES … WRITE)任何请求
如果一个事务想在表中行加S锁,那么必须先获取IS锁
如果一个事务想在表中行加X锁,那么必须先获取IX锁
MDL锁(Meta Data Lock)
MDL是意向锁的实现,这个锁是表级锁,MDL不需要显式使用,在访问一个表的时候会被自动加上。DML会加一个读锁。
我们经常遇到线上由于业务需要加字段,这个是个比较危险的操作,我们一般选择在业务的低峰期执行。
DDL的操作流程:
- 拿MDL写(X)锁
- 降级成MDL读(S)锁
- 真正做DDL
- 升级成MDL写(X)锁
- 释放MDL锁
如果DDL拿不到MDL写锁,会一直等待,并阻塞在其之后的DML。
快速解决mysql死锁问题
1.首先查看mysql当前的全部线程 使用命令
show processlist;
2.使用这个命令,只能查看这个账户下操作的线程
2.在用kill id,杀死Command为Query 的进程即可。
文章持续更新:欢迎各位小伙伴关注我的公众号:菜丸的程序屋。希望将我的不足之处给予指点,谢谢大家。喜欢Java,热衷学习的小伙伴可以加我微信: CaiWan_Y