MySql事务 Transaction
mysql是默认开启事务,自动提交的
事务的原则—ACID
- 原子性 要么都成功要么都失败
- 一致性 事务前后数据的完整性要保持一致 (转账前后都是1000)
- 持久性 一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。(即使数据库崩溃,一旦重启就会恢复到事务提交后的结果)
- 隔离性 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,事务之间要相互隔离
不隔离所导致的一些问题:
脏读:一个事务读取了另外一个未提交的事务,导致破坏了事务一致性
不可重复读:多次读取的结果是不一致的
幻读:是指一个事务读到了别的事务插入的数据,导致前后读取不一致
事务的四种隔离级别
- READ-UNCOMMITTED—读未提交 一个数据可以读取到其他事务未提交的事务,会出现脏读,隔离级别最低
- READ-COMMITTED—读已提交 读取已提交的事务,不会出现脏读,但由于数据可能被其他事务修改了,俩次读取数据不一样,出现不可重复读现象
- REPEATABLE—可重复读(默认的) 当前事务提交之前,看不到其他事务对数据的修改,保证俩次读取是一样的,但当事务结束后,查询数据结果一定是不同的,出现幻读
- SERIERLIZED—串行化 每个事务依次顺序执行,当前事务提交前,其它事务无法执行任何操作,只能等待,类似线程同步,隔离级别最高
锁 悲观锁和乐观锁
悲观锁
共享锁 —Share Lock
当前事务加上共享锁后,其它事务对该数据只能查询不能修改,除非当前事务提交或回滚
其它事务可以对这个数据再加共享锁,但不能再加独占锁了
【加锁方法】
select语句默认不加任何锁,在语句末尾加上lock in share mode实现加共享锁
update/insert/delete语句默认会自动加上表共享锁
独占锁/排他锁 —Exclusion Lock
当前事务给数据加上独占锁后,其它事务对该数据既不能查询(只能看到修改前的老数据),也不能修改,除非当前事务提交或回滚
其它事务不能再对这个数据加任何类型的锁
【加锁方法】
==update/insert/delete语句默认会自动为操作涉及的行加上独占锁 ==
select语句末尾加上for update实现加独占锁
每一条DDL语句默认自动给表加上独占锁
乐观锁—optimistic Lock
乐观锁的功能需要编写程序实现,或使用ORM框架(如Hibernate / MyBatis plus)提供的乐观锁配置功能
update table set k=k+1 where id =3 具有事务特性吗?(重点)
不具备!!
这个跟i=i+1是一个道理,本身是三步操作 读 -> 改 -> 写,所以并发场景下会有问题,不具有一致性!!!
数据库设计的三大范式
第一范式
- 表中所有列不可再分
第二范式
- 表中所有列都跟主键有关
第三范式
- 表中所有列仅跟主键有关
【企业面试题】SQL优化策略总结
(1)select子句尽量使用列名,而不是*
(2)where子句中条件过滤的解析顺序是从右向左的,对于and条件应尽量把可能为假的条件放在右边,对于or条件应尽量把可能为真的条件放在右边
(3)尽量使用where先过滤掉不满足条件的记录行,再分组
(4)多表连接时,尽量使用SQL99的写法,查询优化而且结构清晰
(5)尽量使用多表连接查询,而不要使用子查询,因为子查询要发出多条查询语句,效率低
(8)给经常出现在where过滤条件的字段添加索引,以便加快查询速度