关系性数据库需要遵循ACID规则
原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性: 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
并发事务将会带来一系列的问题
最常见的是以下三种:
- 脏读:A读到B **没确认** 的数据,B会随时 **“反悔 / 变卦”** ;
- 不可重复读:A想获取data × 2次,结果data **中间被B改掉**,A获取的data **前后不一致**;
- 幻读:由于**B的抢先插入**,导致A **“读不出、插不进”**
数据库事务的隔离级别
1、Read uncommitted(读未提交)就是一个事务可以读取另一个未提交事务的数据。
2、Read committed(读提交)就是一个事务要等另一个事务提交后才能读取数据。
3、Repeatable read(可重复读)就是在开始读取数据(事务开启)时,不再允许修改操作。
4、Serializable(序列化)在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。是最高的事务隔离级别,但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
事务的作用就是保证数据的一致性、完整性。事务隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大,因此很多时候必须在并发性和性能之间做一个权衡。所以设立了几种事务隔离级别,以便让不同的项目可以根据自己项目的并发情况选择合适的事务隔离级别,对于在事务隔离级别之外会产生的并发问题,在代码中做补偿。
msyql优化经验
1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2、应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。
3、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
4、任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
5、避免频繁创建和删除临时表,以减少系统表资源的消耗。
日常工作中是怎么优化SQL
1、加索引,增加索引是一种简单高效的手段,但是需要选择合适的列,同时避免导致索引失效的操作,比如like、函数等。
2、避免返回不必要的数据列,减少返回的数据列可以增加查询的效率。
3、根据查询分析器适当优化SQL的结构,比如是否走全表扫描、避免子查询等
4、分库分表,在单表数据量较大或者并发连接数过高的情况下,通过这种方式可以有效提升查询效率
5、读写分离,针对读多写少的场景,这样可以保证写操作的数据库承受更小的压力,也可以缓解独占锁和共享锁的竞争。
MVVC如何实现事务的隔离
MVVC是一种用来解决读-写冲突的无锁并发控制,简单总结就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 所以MVCC可以为数据库解决以下问题:在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能;同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题。
MVVC的实现,依赖4个隐式字段,undo日志 ,Read View 来实现的。
MVCC主要由下面两个核心功能组成,undo log实现数据的多版本,ReadView实现多版本的并发控制。
1. 当一个事务尝试改动某条数据时,会将原本表中的旧数据放入undo log中。
2. 当一个事务尝试查询某条数据时,MVCC会生成一个ReadView快照。