资讯中心

3 数据库事务

📅 2026/7/9 1:05:03
3 数据库事务
1. 转账操作转账是从一方扣钱另一方加钱采用数据库来模拟一下这个操作# 创建一个账户表createtableaccount(idbigintprimarykeyauto_incrementcomment账户,namevarchar(16)notnullcomment账户名称,moneybigintnotnullcomment账户余额)comment账户表;# 添加两个账户信息张三、李四一人1000大洋insertintoaccount(name,money)values(张三,1000),(李四,1000);# 模拟张三给李四转500大洋updateaccountsetmoneymoney-500whereid1;updateaccountsetmoneymoney500whereid2;转账分为两个操作需要先给一个用户扣钱再给一个用户加钱第一个扣钱的操作成功了但是因为一些其他的原因比如服务器断点或者是一些异常情况导致第二个加钱的SQL执行失败。整个转账的业务其实是失败的但是第一个的钱扣了没了。。。。。正常应当是这两个操作要么都执行成功要么都执行失败上述的转账问题就可以基于事务来解决事务可以看做是一个最小的执行单位一个事务可以由一条或者多条SQL语句组成。 一个事务操作所有的SQL语句要么都执行成功要么都执行失败。2. 事务操作首先MySQL就是开启事务的但是这个事务每执行一个DML语句都会自动的提交结束开启事务1.因为MySQL默认自动结束事务的咱们可以自己关闭这种自动结束的操作。2.也可以通过单独的指令来指定事务开始和结束的位置setAutoCommit0;--默认情况值是1代表每次自动结束事务设置为0代表需要咱们手动的结束事务。 begin;--开启手动结束事务操作需要在执行完SQL语句后自己去执行结束事务的指令 start transaction;--跟begin是一样的。。。。结束事务1.如果开启事务的所有SQL语句执行没有问题可以直接提交事务。2.如果开启事务后执行的SQL语句存在问题可以执行回滚事务操作。commit;--提交事务事务中的操作都会落到磁盘当众 rollback;--回滚事务事务中的操作全部都会恢复到事务开启之前的状态。将前面的转账操作基于事务控制解决前面的问题# 模拟张三给李四转500大洋setAutoCommit1;-- 关闭自动结束事务需要遇到commit或者rollback才会结束这个事务begin;-- 手动开启了一个事务需要遇到commit或者rollback才会结束这个事务。starttransaction;-- 也是手动开启一个事务。updateaccountsetmoneymoney-500whereid1;updateaccountsetmoneymoney500whereid2;commit;rollback;-- 事务结束有两种方式。commit提交。 rollback回滚。3. 事务的基本实现原理4. 事务的特性原子性Atomicity事务是一个最小的执行单位一次事务的操作要么都成功要么都失败。一致性Consistency表示一个事务内有一个操作失败时所有的更改过的数据都必须回滚到修改前的状态。隔离性Isolation事务查看数据操作时数据所处的状态要么是另一个并发事务修改之前的状态要么是另一个事务修改它之后的状态事务不会查看中间状态的数据。持久性Durablility事务正常提交后会将数据落到磁盘中影响是永久了。5. 事务并发问题脏读一个事务中读取到了另一个事务未提交的数据。这个问题必须要解决不可重复读一个事务中多次查询同一个数据结果不一致。原因是其他事务中对这个数据修改了并且提交事务了。幻读一个事务中多次查询同一个数据结果不一致。原因是其他事务中对某个数据进行了增删并且提交事务了。为了复现上述的问题优先将MySQL的事务隔离级别调低-- 为了查看到所有问题的效果这里优先将事务的隔离级别设置为最低等级。READ-UNCOMMITTED。setglobaltransaction_isolationREAD-UNCOMMITTED;-- 因为设置的是全局的事务隔离级别设置完毕后关闭连接重新打开才会生效。selecttransaction_isolation;复现脏读效果复现不可重复读效果复现幻读的效果6. 事务的隔离级别READ-UNCOMMITTED读未提交可以读取到未提交事务的数据。一个问题都不能解决READ-COMMITTED读已提交可以读取到已经提交事务的数据。只能解决脏读Oracle默认隔离级别是READ-COMMITTEDREPEATABLE-READ可重复读会让一次事务多次查询同一数据结果一致修改导致。可以解决脏读和不可重读MySQL默认隔离级别是可重复读REPEATABLE-READSERIALIZABLE串行化上锁所有问题都能解决。可以解决所有问题为了解决上面的各种问题这里可以设置事务的隔离级别然后查看效果查看事务的隔离级别的方式selecttransaction_isolation;设置事务的隔离级别可以设置全局的也可以针对当前连接设置。-- 全局的事务隔离级别设置。设置完需要关闭连接重新打开setglobaltransaction_isolationSERIALIZABLE;-- 当前会话的事务隔离级别设置。setsessiontransaction_isolationSERIALIZABLE;