Mysql事务管理

1:原子性

要么执行成功,要么回滚到最初的状态,(要么做,要么不做)不能处于中间状态,也就是说事务是一个完整的整体,不能被分割

2:一致性

事务的开始和结束后,数据库的完整性约束不能被破坏.比如A向B转账,不能A转出去了,A少了钱,B没有收到钱

3:隔离性

同一时间,只允许同一个事务请求同一条数据,其他事务不能操作这条数据,也就是说事务之间不能相互干扰.比如A在取钱,B不能向A账户转账

4:持久性

事务完成后,操作的数据都要保存到数据库,不能回滚

5:事务的隔离级别

A: READ UNCOMMITTED:幻读,不可重复读和脏读均允许

B: READ COMMITTED:允许幻读和不可重复读,但不允许脏读

C: REPEATABLE READ:允许幻读,但不允许不可重复读和脏读

D: SERIALIZABLE:幻读,不可重复读和脏读都不允许

ORACLE默认的是 READ COMMITTED

MYSQL默认的是 REPEATABLE READ

如果数据库的隔离级别为READ_UNCOMMITTED, 则其他线程可以看到未提交的数据, 因此就出现脏读;

如果数据库隔离级别设为READ_COMMITTED,即没提交的数据别人是看不见的,就避免了脏读;但是,正在读取的数据只获得了读取锁,读完之后就解锁,不管当前事务有没有结束,这样就容许其他事务修改本事务正在读取的数据。导致不可重复读。

REPEATABLE READ因为对正在操作的数据加锁,并且只有等到事务结束才放开锁, 则可以避免不可重复读;

REPEATABLE READ只能保证正在被本事务操作的数据不被其他事务修改,却无法保证有其他事务提交新的数据。 则有可能线程1在操作表T1的时候(特别是统计性的事务),其他线程仍然可以提交新数据到表T1,这样会导致线程1两次统计的结果不一致,就像发生幻觉一样。

SERIALIZABLE因为获得范围锁,且事务是一个接着一个串行执行,则保证了不会发生幻读。

由此可见,隔离级别越高,受其他事物干扰越少,并发性能越差。

二个或以上事务在操作同一个共享记录集时,可能会出现的问题:

      (A)脏读 (B)不可重复读 (C)幻读

      隔离级别:

      (1)read-uncommit, (2)read-commit, (3)read-repeatable, (4)read-serializable

      都是用来阻止上面的问题的,其中:

      (1)什么都阻止不了。

      (2)阻止(A)

      (3)阻止(A)(B)

      (4)阻止(A)(B)(C)

      (1)->(4)隔离级别越高,性能损失越大。

自己的理解(关于脏读,不可重复读,幻读)

      ※脏读:一个事务读取了另一个未提交的并行事务写的数据。

      (事务T1更新了一行记录的内容,但是并没有提交所做的修改。事务T2读取更新后的行,然后T1执行回滚操作,取消了刚才所做的修改。现在T2所读取的行就无效了。)

      

      exp:

      小明的分数为89,事务A中把他的分数改为98,但事务A尚未提交。

      与此同时,

      事务B正在读取小明的分数,读取到小明的分数为98。

      随后,

      事务A发生异常,而回滚了事务。小明的分数又回滚为89。

      最后,

      事务B读取到的小明的分数为98的数据即为脏数据,事务B做了一次脏读。

      (大部分数据库缺省的事物隔离级别都不会出现这种状况)

      

      ※不可重复读:一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过。

      (事务T1读取一行记录,紧接着事务T2修改了T1刚才读取的那一行记录。然后T1又再次读取这行记录,发现与刚才读取的结果不同。这就称为“不可重复”读,因为T1原来读取的那行记录已经发生了变化。)

      exp:

      在事务A中,读取到小明的分数为89,操作没有完成,事务还没提交。

      与此同时,

      事务B把小明的分数改为98,并提交了事务。

      随后,

      在事务A中,再次读取小明的分数,此时工资变为98。在一个事务中前后两次读取的结果并不致,导致了不可重复读。

      ※幻读:一个事务重新执行一个查询,返回一套符合查询条件的行,发现这些行因为其他最近提交的事务而发生了改变。

      (事务T1读取一条指定的WHERE子句所返回的结果集。然后事务T2新插入 一行记录,这行记录恰好可以满足T1所使用的查询条件中的WHERE 子句的条件。然后T1又使用相同的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突 然出现的一样。)

      exp:

      目前分数为90分以上的的学生有15人,事务A读取所有分数为90分以上的的学生人数有15人。

      此时,事务B插入一条分数为99的学生记录。

      这是,事务A再次读取90分以上的的学生,记录为16人。此时产生了幻读。

      (大部分数据库缺省的事物隔离级别都会出现这种状况,此种事物隔离级别将带来表级锁)

※ MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持!

6:drop,delete与truncate的区别

Drop:删除整个表结构

Delete:删除行级别的数据

Truncate:删除全部数据,表空间和索引的空间回到最初的样子,删除后的数据id从一开始

7:索引

作用:快速查询和更新表中的数据

优点:

一:通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

二:可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

三:可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

四:在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

五:通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

总结:查询速度会变快很多

缺点:

一:创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

二:索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

三:当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

总结:索引过多占用空间

8:创建索引的列

1:在经常搜索的列上

2:主键列

3:连接的列上,外键列

4:经常根据范围搜索的列上

5:经常排序的列上

6:经常使用where的列上

9:不应创建索引的列

1:查询中很少使用或者参考的列不应该创建索引

2:对于该列很少创建索引的列

3:对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

4:当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

总结: 根据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引

唯一索引:这一列索引中不允许有相同值

主键索引:在主键上加索引,主键索引是唯一索引的一种特定形式

聚集索引: 聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么可以想象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

10:使用索引技巧

   1.索引不会包含有NULL的列

       只要列中包含有NULL值,都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此符合索引就是无效的。

    2.使用短索引

       对串列进行索引,如果可以就应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是唯一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

    3.索引列排序

       mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作,尽量不要包含多个列的排序,如果需要最好给这些列建复合索引。

    4.like语句操作

      一般情况下不鼓励使用like操作,如果非使用不可,注意正确的使用方式。like ‘%aaa%’不会使用索引,而like ‘aaa%’可以使用索引。

    5.不要在列上进行运算

    6.不使用NOT IN 、<>、!=操作,但<,<=,=,>,>=,BETWEEN,IN是可以用到索引的

    7.索引要建立在经常进行select操作的字段上。

       这是因为,如果这些列很少用到,那么有无索引并不能明显改变查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

    8.索引要建立在值比较唯一的字段上。

    9.对于那些定义为text、image和bit数据类型的列不应该增加索引。因为这些列的数据量要么相当大,要么取值很少。

    10.在where和join中出现的列需要建立索引。

    11.where的查询条件里有不等号(where column != …),mysql将无法使用索引。

    12.如果where字句的查询条件里使用了函数(如:where DAY(column)=…),mysql将无法使用索引。

    13.在join操作中(需要从多个数据表提取数据时),mysql只有在主键和外键的数据类型相同时才能使用索引,否则及时建立了索引也不会使用。

11:连接的种类

1:左连接:左表的数据全部显示,右表的数据有就显示,没有就为空;如果右表有,左表没有,则不显示left join

2:右连接:与左连接相反 right join

3:内连接:返回相同部分的数据   join 或 inner join

12:sql优化

1)应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
2)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null,然后这样查询:
select id from t where num=0
3)很多时候用 exists 代替 in 是一个好的选择
4)用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤

13:mysql和Oracle区别

1:Oracle是大型数据库,MySQL是中性数据库    oracle市场占有率为0.4,mysql市场占有率为0.2,同时mysql是开源的,Oracle价格及贵

2:oracle 高并发效果好

3:空间mysql小.,Oracle占用空间大

4:Mysql主键有自增长,Oracle主键没有自增长

5:Mysql可以用单引号和双引号包字符串,但是Oracle只能用单引号

6: MYSQL处理翻页的SQL语句比较简单,用LIMIT 开始位置, 记录个数;ORACLE处理翻页的SQL语句就比较繁琐了。每个结果集只有一个ROWNUM字段标明它的位置, 并且只能用ROWNUM<100, 不能用ROWNUM>80

猜你喜欢

转载自www.cnblogs.com/fupenghui/p/9025471.html