Mysql事务使用总结

事务使用总结:

MySQL事务主要用来处理数据量大、数据复杂度高的数据操作,最经典的使用场景是银行的转账:需要先从银行账户A中取出钱,然后再存入银行账户B中,如果中间出现问题,而没有事务的保证,那么就会出现B收不到钱,而A支出钱又回不到自己的账户的严重问题,那么有了事务机制,这个问题就解决了。

 

事务的特点

事务的ACID

事务的锁定

事务的隔离

事务的使用

 

一、事务的特点

1、在mysql中,只有数据库引擎InnoDB支持事务机制;

2、事务可用来维护数据结构及数据的完整性,确保批量的操作要么全部执行,要么全部不执行;

3、事务是用来管理数据表的insert、update及delete的

 

二、事务的ACID

1、A(Atomicity),即事务的原子性

一组事务操作,要么都成功,要么都撤回。

2、C(Consistency),即事务的稳定性

有非法数据操作,如:外键约束,事物撤回。

3、I(Isolation),即事务的隔离性

事务是独立运行的,一个事务的操作如果影响了另一个事物,那么另一个事务就会撤回执行,要做到事务100%的隔离,需要牺牲速度和性能。

4、D(Durability),即事务的可靠性

当数据库崩溃之后,InnoDB数据库表驱动会利用日志文件进行数据的重构修改,需要注意的是:安全性和性能速度不可兼得。

 

三、事务的隔离

1、并发时遇到的问题

在事务并发操作时,经常出现一些问题,这些问题可用几个术语名词描述:

A、脏读

一个事务读取了另一个事务并发写的未提交的数据,比如:事务A读取了事务B写入的数据,但是B事务并未提交,后来其撤销了修改,此时事务A就读取了不该读取的数据。

 

B、幻读

一个事务重复读取数据,在获得的数据行中发现某些数据是其它事务最近操作的数据,比如:事务A反复执行查询语句查询数据表,而这时另一事务B正在操作该表,恰好的是事务B操作的数据正符合事务A查询的条件,而事务A再读取时,发现结果集发生了变化,这在并发事务时经常出现。

 

C、不可重复读

一个事务重复读取之前读取过的数据,后发现读取的数据被另一个事务所修改,比如:事务A反复读取指定的数据,而此时事务B正好操作该数据,当事务A再次查询时,发现之前读取的数据已经变化。

 

注:

上面事务并发出现的问题,可以通过设置事务的隔离来处理,但不能完全依赖事务隔离,而是应该在应用程序中恰当的使用锁来控制并发访问,两者的结合是解决的问题关键。

 

2、事务的隔离级别

事务隔离级别分为4种:

READ UNCOMMITED // 允许幻读,脏读及不可重复读;

READ COMMITED   // 允许幻读和不可重复读,不允许脏读;

REPEATABLE READ // 允许幻读,不允许脏读和不可重复读;

SERIALIZABLE READ // 不允许幻读,脏读及不可重复读;

 

注:

Mysql默认的是REPEATABLEREAD级别。另外,随着事务的隔离级别越高,并发执行的性能就越低,所以适当选择级别并结合业务需求来选定级别设置。

 

3、设置事务隔离级别

A、查询Mysql系统隔离默认级别:

Mysql> SELECT @@global.tx_isolation;

结果:

@@global.tx_isolation

REPEATABLE-READ

 

B、查询Mysql会话隔离默认级别:

Mysql> SELECT @@tx_isolation;

结果:

@@tx_isolation

REPEATABLE-READ

 

C、修改系统及会话隔离级别

这里我们将事务的级别修改为READ COMMITED:

mysql> SET global transaction isolation level readcommitted;

mysql> SET session transaction isolation level readcommitted;

结果:

 

四、事务的锁定

为什么要给事务加锁?是因为高并发访问操作数据时,会存在正在读取某数据时,其它进程会删除会修改该数据,为了保证数据的完整性,需要对进程共享数据加锁控制。

 

事务锁的分类:

按照对数据的操作类型划分:

读锁(共享锁)-

针对同一块数据,多个读操作可同时进行互补影响。

 

写锁(排它锁)-

针对同一块数据,当前写操作未完成,它会阻止其它操作进行。

 

按照锁定数据的范围划分:

表锁 -

MyIsam引擎默认使用的锁。当写入数据时,把整张表锁住,其它的读,写操作都不进行,一律等待当前写操作完成,特点:开销小,并发量小。

 

行锁 -

InnoDB及Falcon引用默认使用的锁。当写入数据时,把当前操作的数据行锁定,其它读,写操作一律等待,特点:开销适中,并发量大。

 

注:

Mysql是一种开放式数据库架构,是允许自定义存储引擎的,而Oracle及Sql server是不允许自定义修改的。

 

五、事务的使用

1、事务的操作

开启一个事务:

START TRANSACTION | BEGIN;

 

提交关闭事务;

COMMIT;

 

保存事务快照:

SAVE POINT save_point_name;  // save_point_name保存事务点名字

 

回滚事务(点):

ROLLBACK save_point_name;

 

2、PHP使用事务

这里以关联数据表t_product_item和 t_product_detail为例说明事务的使用。这两张表是通过外键关联的,这里为了模拟验证事务的原子特性,故向两张数据表中插入数据,首先向t_product_item插入数据成功,而t_product_detail插入失败,那么因为使用了事务机制,所以t_product_item插入成功的数据会恢复插入前数据条数)。

 

A、php代码

<?php

// 链接mysql

       $conn =mysql_connect('localhost','root','');

       if(!$conn) {

           echo 'Could notconnect the db server!';

           return;

       }

       

       // 选择数据库

       mysql_select_db('db_study_mysql');

       /* 事务处理 */

       // 设置事务不自动提交 因为默认mysql自动提交

       mysql_query('SET AUTOCOMMIT =0');

       // 开始事务定义

       mysql_query('BEGIN');

       // 如果插入数据失败 则回滚

       $piSQL = 'INSERT INTOt_product_item(pino,piname,piimage,piprice,pifid) VALUES(';

       $piSQL .='"PINO20160320003"'.','.'"顶级肥牛"'.','.'"http://images.cwteam.com/uploads/imgs/2016320001/23123212.jpg"'.',';

       $piSQL .= '60.00'.','.'2'.');';

       

       $piID = mysql_query($piSQL,$conn);

       if($piID) {

           echo '向t_product_item插入数据成功!</br>';

           

           $pdSQL = 'INSERT INTOt_product_detail(pdno,pdname,pdprice,pddesc,pdrule,pdfid) VALUES(';

           $pdSQL .= '顶级肥牛'.','.'http://images.cwteam.com/uploads/imgs/2016320001/23123212.jpg'.',';

           $pdSQL .= '60.00'.','.'法式小餐厅,由顶级餐厅大厨掌勺定制,赶紧来吧,限时抢购中,截止23号'.',';

           $pdSQL .= '材质不详,但好吃哦!'.','.'4'.');'; // 因为pdfid外键值 不存在4 所以插入会失败

           

           $pdID =mysql_query($pdSQL,$conn);

           if($pdID) {

              echo '向t_product_detail插入数据成功!</br>';

           } else {

              echo '向t_product_detail插入数据失败,已经回滚事务!</br>';

              mysql_query('ROLLBACK');

           }

       } else {

           echo '向t_product_item插入数据失败,已经回滚事务!</br>';

           mysql_query('ROLLBACK');

       }

       

       // 提交关闭事务

       mysql_query('COMMIT');

       // 关闭数据库链接

       mysql_close($conn);

 

?>

B、浏览器结果:

 

C、数据库结果:

因为使用事务,所以这里的t_product_item数据不变,对比使用事务的前后,这里不做介绍,因为本人已经测试过没问题。

Ps:感兴趣的同学最好验证下。

 

好了,到这里关于Mysql的事务已经总结介绍完了,如有问题请及时讨论纠正,谢谢。

 

 

博主新站点:http://www.wang-chao.cn/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值