58数据库3_transaction

 

 

 

transaction

事务,由若干条语句组成的,指要做的一系列操作;

InnoDB引擎,支持事务;

 

ACID

atomicity,一个事务是一个不可分割的工作单位,事务中包括的所有操作要么全部做完,要做什么都不做;

consistency,事务必须是使数据库从一个一致性状态变成另一个一致性状态,一致性和原子性是密切相关的;

isolation,一个事务的执行不能被其它事务干扰,即一个事务内部的操作及使用的数据对并发的其它事务是隔离的,并发执行的各个事务之间不能互相干扰;

durability,持久性也称永久性permanence,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其它操作或故障不应该对其有任何影响;

 

注:

atomicity要求事务中的所有操作,不可分割,不能做了一部分操作,还剩一部分操作;

consistency,多个事务并行执行的结果,应该和事务排队执行的结果一致,如果事务的并行执行和多线程读写共享资源一样不可预期,就不能保证一致性;

isolation,指多个事务访问共同的数据了,应该互不干扰,隔离性指究竟在一个事务处理期间,其它事务能不能访问的问题;

durability,事务提交后,数据不能丢失;

 

 

隔离性不好,带来的问题:

1lost update更新丢失:

不允许事务A和事务B并行;

例,事务A和事务B,更新同一个数据,它们都读取了初始值100A要减10B要加100A减去10后更新为90B100更新为200A的更新丢失了;

 

2dirty read脏读:

只用于展示可以,用于计算可以;

事务B读到了事务A未提交的数据,这个数据可能是一个中间值,也可能事务A之后回滚事务,事务A是否最后提交并不关心,只要读到了这个被修改的数据就是脏读,隔离不好,读到了未提交的数据(中间状态值);

 

3unrepeatable read不可重复读:

允许后一次可读到正确的内容;

不能保证同一条查询语句重复读相同的结果,就是不可重复读;

例,事务A在同一事务中执行相同查询语句(先后查询了2次),得到了不同的结果(不能重复的获取相同数据);

例,事务A在查询了一次后,事务B修改了数据,事务A又查询一次,发现数据不一致了;没说提交;

注:脏读是可以读到相同数据的,但读取的是一个未提交的数据,不是提交的最终结果;

 

4phantom read幻读:

例,事务A中同一个查询要进行多次,事务B插入数据,导致事务A返回了不同的结果集,如同幻觉;

数据集有记录增加了,可以看作是增加了记录的不可重复读;

 

有以上问题,数据库必须要解决,解决办法:1、隔离级别;2、加锁;

 

隔离级别

由低到高,依次为:

read uncommitted,读取到未提交数据,读不受约束;

read commited,读已经提交的数据,oralce默认;

repeabable read,可以重复读,MySQL默认,解决不可重复读;

serializable,串行化,事务间完全隔离,不能并发只能串行,解决了所有问题;

 

隔离级别越高,串行化越高,数据库执行效率越低,当前事务处理的中间结果对其它事务不可见程度越高;

隔离级别越低,并行度越高,性能越高;

 

会话级别|全局级别:

>set [session|global] transaction isolation level LEVEL;   #生产中慎用global

>select @@global.tx_isolation;

>select @@tx_isolation;

>set session transaction isolation level read committed;

 

serializable,串行了,解决所有问题;

 

repeatable read

事务A中同一条查询语句返回同样的结果,就是可以重复读数据了,解决办法有:

1、对select的数据加锁,不允许其它事务有删除、修改操作,如for update

2、第一次select时,对最后一次确切提交的事务的结果的快照;

以上解决了不可重复读,但有可能出现幻读

 

read committed

在事务中,每次select可以读到别的事务刚提交成功的新的数据,因为读到的是提交后的数据,解决了脏读,但不能解决不可重复读的问题

 

read uncommitted

能读取到别的事务还没提交的数据,完全没有隔离性可言,出现了脏读

 

事务语法:

>start transaction   #>begin开始一个事务,>start transaction是标准sql语法;

>commit   #提交事务后,变更成为永久变更;

>rollback   #可在提交事务之前,回滚变更,事务中的操作就如同没有发生过一样;

>set autocommit=0   #默认autocommit模式,可禁用或启用,用于当前连接,出错也可自动回滚,0禁用自动提交事务,如果开启自动提交,若有一个修改表的语句,执行后会立即把更新存储到磁盘;开发时一般会关掉此项,性能问题,是一批批的提交,而不是一句句的提交;

 

 

数据仓库和数据库的区别:

本质上来说没有区别,都是存放数据的地方;

数据库支持在线业务,需要频繁增删改查;数据仓库一般囤积历史数据支持用于分析的SQL,一般不建议删改;

 

数据库关注数据的持久化、数据的关系,为业务系统提供支持、事务支持;

OLTP,在线交易数据,数据库;

 

数据仓库,存储的数据是为了分析或者发掘而设计的表结构,可以存储海量数据;

数据仓库存储历史数据用于分析OLAP

 

 

其它概念:

cursor游标:

操作查询的结果集的一种方法;

可将游标当作一个指针,指向结果集中的某一行;

 

stored procedure存储过程、trigger触发器:

这两种技术是DB的高级内容,但基本很少用了,逻辑前移,BS|CS放在BC上了;

stored procedure,数据库系统中,一段完成特定功能的SQL语句,编写成类似函数的方式,可以传参并调用,支持流程控制语句;

trigger,由事件触发的特殊的存储过程,如Insert数据时触发;trigger功能虽强大,但会有性能问题;

 

 

例:

mysql> set autocommit=0;

mysql> show variables like 'autocommit';

mysql> show variables like 'tx_isolation';

mysql> select * from t;

mysql> set session transaction isolation level read committed;

 

注:

set autocommit=0;关闭自动提交;

两个窗口均默认级别REPEATABLE-READ

Aupdate t set id=4 where id=2

A端未commitA端查询是改变后的状态,B端查询没变化,

Acommit后,A端查询是改变后的状态,B端查询没变化,

Bcommit后,B端查询是改变后的状态;

 

两个窗口用READ-COMMITTED>set session transaction isolation level read committed;

Ainsert into t values(6,'ftp',28);

A端未commitA端查询是改变后的状态,B端查询没变化;

AcommitA端查询是改变后的状态,B端查询是改变后的状态;

 

mysql> select * from t for update;   #InnoDB是行级锁,此句相当于表级锁;使用时,用几行加几行锁,且加锁时间越短越好

mysql> commit;   #commit,其它窗口的mysql> update t set id=5 where id=6;更新语句会卡住