生产环境中事务的应用场景:
事务是多个数据库操作的集合,该集合内必须所有的数据库操作完成,事务才能完成,只要有一个操作失败,事务就不会成功,之前成功的数据库操作会进行回滚以保证事务的完整性不会遭到破坏,因此事务具有不错的安全性!
事务的四个特性,简称为ACID,这是这四个特性的英文头个字母。
一:原子性(Atomic)
所谓原子性就是指的事务的不可分割性,原子是最小的单位,所以理解事务的原子性就是理解事务无法进行分割,事务里的数据库操作要么全部成功,要么全部失败,不可能出现一部分成功,一部分失败的情况,这就是原子性。
二:一致性(Consistent)
事务操作会确保数据库状态保持一致性,事务提交前和提交后数据库状态会发生改变,但会保持一致性,例如购买商品,一旦完成一笔交易的事务,数据库里的商品数必然减1,同时商店收益必然增加,这就是保持了数据库状态的一致性。
三:隔离性(Isolated)
隔离性指的是事务间是相互独立的,不会互相影响,例如点餐过程为一个事务,从电话订购到做出饭菜送餐完成结算完成所有这些操作为一个事务,不同的人进行点餐操作都是相互独立的,并不会互相影响,这就是事务的隔离性,如果一个事务影响了其他的事务,其他的事务将会进行回滚,就如上面的点餐例子,如果饭菜已经卖完,最后点餐的事务将会影响后面的事务,因为没有餐可点了,那么后面的事务将会回滚。
四:持久性(durable)
事务提交的结果或者效果在出现各种故障(例如断网、服务器出问题之类的)的情况依旧能够保存下来,这就是事务的持久性。
选择合理的存储引擎操作事务
InnoDB 是事务型数据库的首选引擎,支持事务安全表 ACID
MysqL 5.7 以后默认 InnoDB 引擎;
MysqL 5.5 以前默认 MyISAM引擎,需事务处理时,另设置InnoDB引擎;
查看当前的默认引擎:
show engines;
针对已经设置过的表,如何修改存储引擎:
alter table stu engine = 'innodb';
或者直接图形化软件里修改,比如我的navicat
事务单独开启机制:
开始一个事务
start transaction或者begin
回退一个事务
rollback(全部回退)
提交一个事务
commit
全局事务使用方法:
set autocommit=0或者1 //0为不自动提交,1为自动提交,默认为1
这里autocommit也可以直接在MysqL的配置文件里更改,windows是改my.ini文件,linux是改my.cnf文件
在[MysqLd]下加入autocommit=0/1即可。
set autocommit = 0; insert into lesson(lesson) values(PHP'); commit;
PHP中使用事务的实例:
<?PHP $config = [ 'host' => '127.0.0.1','user' => 'root','password' => '123456','database' => 'fa','charset' => 'utf8' ]; $dns = sprintf( "MysqL:host=%s;dbname=%s;charset=%s",$config['host'],1)">$config['database'],1)">$config['charset'], ); // echo $dns; try{ $pdo = new PDO($dns,1)">$config['user'],1)">$config['password']); var_dump($pdo); $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); }catch(PDOException $e){ die($e->getMessage()); } 演示事务 $pdo->beginTransaction(); exec('insert into stu(sname,class_id,sex) values("cyy10",2,"女")'); throw new Exception('没有操作权限哦~'); commit(); }){ rollBack(); getMessage()); }
事务隔离级别与脏读实例:
查询隔离级别
select @@tx_isolation;
在cmd界面登录MysqL,查询事务隔离级别的时候,报错:未知系统变量 'tx_isolation
解决办法:
由于MysqL数据库的更新,在旧版本中tx_isolation是作为transaction_isolation的别名被应用的,新版本已经弃用了,所以输入会显示未知变量
把tx_isolation换成transaction_isolation,就可以显示结果。
设置隔离级别
set session transaction isolation level read uncommitted;
脏读指的是一个事务修改本事务的数据,但没有提交的情况下,本事务可以查看到更改了却没有提交的数据。这种情况只可能发生在未提交读readuncommitted的隔离级别里。
事务回滚后可以看到两次读取情况不一致;
高并发带来的不可重复读的隔离级别设置:
不重复读:指的是一个事务多次读取同一个数据,但此过程中第二个事务对第一个事务进行了修改,这就造成了第一个事务的多次读取过程中的结果出现了前后不一致的情况,这就是不可重复读!这个情况可以出现在read-uncommited和read-committed两个隔离级别里!
幻读实例操作与隔离级别处理:
在repeatable-read级别下解决了不可重复读的问题,但是还有没有解决的地方,那就是幻读,幻读是指在一个事务中,事务一对数据进行了更改并提交了,而事务二也对该数据进行了更改,但是更改的情况可能会受到事务一更改的影响,从而引起更改仿佛不存在,这就是幻读!这是由于repeatable-read的隔离措施只读取初次select的点导致的。
提交读解决了脏读问题,而重复读解决了不重复读的问题,串行化解决幻读的问题,但是也会造成锁竞争,可能造成大量的超时问题,因为串行化是给每个读的数据行加上共享锁,通过强制事务进行排序,以此防止相互冲突