MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持的!***:一般MYSQL数据库默认的引擎是MyISAM,这种引擎不支持事务!如果要让MYSQL支持事务,可以自己手动修改:
方法如下:
1.修改c:apervmysqlmy.ini文件,找到skip-InnoDB,在前面加上#,后保存文件。
2.在运行中输入:services.msc,重启mysql服务。
3.到中,mysql->show engines;(或执行mysql->show variables like ‘have_%’; ),查看InnoDB为YES,即表示支持InnoDB了。
也就说明支持事务transaction了。
4.在创建表时,就可以为Storage Engine选择InnoDB引擎了。如果是以前创建的表,可以使用
代码如下复制代码 mysql->alter table table_name type=InnoDB;
或
mysql->alter table table_name engine=InnoDB;
来改变数据表的引擎以支持事务。
事务回滚在事务中,每个正确的原子操作都会被顺序执行,直到遇到错误的原子操作,此时事务会将之前的操作进行回滚。回滚的意思是如果之前是插入操作,那么会执行删除插入的记录,如果之前是update操作,也会执行update操作将之前的记录还原。因此,正确的原子操作是真正被执行过的。
MYSQL的事务处理主要有两种方法。
1、用begin,rollback,commit来实现
begin 开始一个事务
rollback 事务回滚
commit 事务确认
2、直接用set来改变mysql的自动提交模式
MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们可以通过
set autocommit=0 禁止自动提交
set autocommit=1 开启自动提交
来实现事务的处理。
当你用 set autocommit=0 的时候,你以后所有的SQL都将做为事务处理,直到你用commit确认或rollback结束。
注意当你结束这个事务的同时也开启了个新的事务!按第一种方法只将当前的作为一个事务!
PHP实现MySQL事务回滚
创建一个测试的:
先见AI
数据为基,先见未见
95 查看详情
代码如下复制代码
mysql> CREATE DATABASE `shop_test` DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
Query OK, 1 row affected (0.00 sec)
mysql> use shop_test;
Database changed
mysql> CREATE TABLE IF NOT EXISTS `user_account`(
-> `user` varchar(20) NOT NULL,
-> `money` INT(10) NOT NULL,
-> PRIMARY KEY (`user`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
Query OK, 0 rows affected (0.51 sec)
mysql> CREATE TABLE IF NOT EXISTS `user_order`(
-> `id` INT(10) NOT NULL,
-> `user` VARCHAR(20) NOT NULL,
-> `price` INT(10) NOT NULL,
-> `count` INT(10) NOT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1;
Query OK, 0 rows affected (0.33 sec)
mysql> INSERT INTO `user_account` VALUES (‘luchanghong’, ‘100’);
Query OK, 1 row affected (0.00 sec)
PHP测试代码:
$conn = mysql_connect(‘127.0.0.1’, ‘root’, ‘root’);
mysql__db(‘shop_test’);
mysql_query(‘SET NAMES UTF8’);
# start transaction
mysql_query(“START TRANSACTION”);
$sql = “INSERT INTO `user_order` VALUES (‘1’, ‘luchanghong’, ’10’, ‘2’)”;
mysql_query($sql);
$sql_2 = “UPDATE `user_account` SET `money` = `money` – 10*2 WHERE `user` = ‘luchanghong'”;
mysql_query($sql_2);
if (mysql_errno()){
echo “error”;
mysql_query(“ROLLBACK”);
}else{
echo “OK”;
mysql_query(“COMMIT”);
}
执行一次后查看数据库:
代码如下复制代码
mysql> SELECT * FROM `user_account`;
+————-+——-+
| user | money |
+————-+——-+
| luchanghong | 80 |
+————-+——-+
1 row in set (0.00 sec)
mysql> SELECT * FROM `user_order`;
+—-+————-+——-+——-+
| id | user | price | count |
+—-+————-+——-+——-+
| 1 | luchanghong | 10 | 2 |
+—-+————-+——-+——-+
1 row in set (0.00 sec)
那么,我添加一个条件,就是每次更新完 user_account 表后检查用户的 money 是否为负值,如果为负值那么就要撤销之前的操作,执行事务回滚。
代码如下复制代码
$conn = mysql_connect(‘127.0.0.1’, ‘root’, ‘root’);
mysql_select_db(‘shop_test’);
mysql_query(‘SET NAMES UTF8’);
// start transaction
mysql_query(“START TRANSACTION”);
$sql = “INSERT INTO `user_order`(`user`, `price`, `count`) VALUES (‘luchanghong’, ’10’, ‘2’)”;
mysql_query($sql);
$sql_2 = “UPDATE `user_account` SET `money` = `money` – 10*2 WHERE `user` = ‘luchanghong'”;
mysql_query($sql_2);
if (mysql_errno()){
echo “error n”;
mysql_query(“ROLLBACK”);
}else{
$money = check_remain_money(‘luchanghong’);
echo $money.” “;
if ($money echo “No enough money n”;
mysql_query(“ROLLBACK”);
}else{
echo “OK n”;
mysql_query(“COMMIT”);
}
}
function check_remain_money($user){
$sql = “SELECT `money` FROM `user_account` WHERE `user` = ‘{$user}'”;
$result = mysql_fetch_assoc( mysql_query($sql) );
return !empty($result) ? $result[‘money’] : 0;
}
接着,在shell下多次执行这php文件(WIN下就手动执行几次吧),例如:
代码如下复制代码
lch@LCH:~/Desktop $ for x in `seq 6`; do php transaction.php ; done
60 OK
40 OK
20 OK
0 OK
-20 No enough money
-20 No enough money
再看数据库数据:
mysql> SELECT * FROM `user_account`;
+————-+——-+
| user | money |
+————-+——-+
| luchanghong | 0 |
+————-+——-+
1 row in set (0.00 sec)
mysql> SELECT * FROM `user_order`;
+—-+————-+——-+——-+
| id | user | price | count |
+—-+————-+——-+——-+
| 1 | luchanghong | 10 | 2 |
| 2 | luchanghong | 10 | 2 |
| 3 | luchanghong | 10 | 2 |
| 4 | luchanghong | 10 | 2 |
| 5 | luchanghong | 10 | 2 |
+—-+————-+——-+——-+
5 rows in set (0.00 sec)
1、为什么auto_increament没有回滚?
因为innodb的auto_increament的计数器记录的当前值是保存在存内 存中的,并不是存在于磁盘上,当mysql server处于运行的时候,这个计数值只会随着insert改增长,不会随着delete而减少。而当mysql server启动时,当我们需要去查询auto_increment计数值时,mysql便会自动执行:SELECT MAX(id) FROM 表名 FOR UPDATE;语句来获得当前auto_increment列的最大值,然后将这个值放到auto_increment计数器中。所以就算 Rollback MySQL的auto_increament计数器也不会作负运算。
2、MySQL的事务对表操作的时候是否是物理操作?
MySQL的事务是有redo和undo的,redo操作的所有信息都是记录到 redo_log中,也就是说当一个事务做commit操作时,需要先把这个事务的操作写到redo_log中,然后再把这些操作flush到磁盘上,当 出现故障时,只需要读取redo_log,然后再重新flush到磁盘就行了。
而对于undo就比较麻烦,MySQL在处理事务时,会在数据共享 表空间里申请一个段叫做segment段,用保存undo信息,当在处理rollback,不是完完全全的物理undo,而是逻辑undo,就是说会对之 前的操作进行反操作,但是这些共享表空间是不进行回收的。这些表空间的回收需要由mysql的master thread进程来进行回收。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/486854.html
微信扫一扫
支付宝扫一扫