Mysql 事务

来源:互联网 发布:文本相似性算法 编辑:程序博客网 时间:2024/06/11 22:25

什么是事务?
通俗点来说, 事务就是对一组由N条SQL语句(N>=1)组成的逻辑处理单元进行并发控制. 当这组SQL语句都执行成功时才会对数据库构成实际影响. 否则只要有一条SQL语句执行失败, 那么整组SQL都不会执行成功, 都不会对数据库有实际影响. 这样能确保这个事务中的这组SQL操作的统一性, 保证数据一致性.

我们来结合实际的例子来理解事务的概念:

-- 在 phpMyAdmin 中执行下面的操作
-- 1, 建立不支持事务的数据表 tbl_a
CREATE TABLE IF NOT EXISTS `tbl_a` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `val` varchar(100) NOT NULL,
  PRIMARY KEY (`id
`)) ENGINE=MyISAM AUTO_INCREMENT=1 ;

-- 2, 为 tbl_a 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行
INSERT INTO tbl_a (val) VALUES ('a');
INSERT INTO tbl_a (val) VALUES ('b');
INSERT INTO tbl_a (vals) VALUES ('c'); -- 因为表中没有 vals 这个字段, 执行到这句时会报错.
INSERT INTO tbl_a (val) VALUES ('d');  -- 因为程序已经中断, 这句不执行

-- 3, 我们来看看 tbl_a 中的数据, 会发现有两条数据.
SELECT * FROM tbl_a;
--   +----+-----+
--   | id | val |
--   +----+-----+
--   |  1 | a   |
--   |  2 | b   |
--   +----+-----+
--   很好理解: 因为我们四条语句一并提交, mysql 还是会一条一条的执行:
--   执行第一句, 没有ERROR, 对数据库产生实际影响, 将 'a' 真真实实的插入到 tbl_a 中
--   执行第二句, 没有ERROR, 对数据库产生实际影响, 将 'b' 真真实实的插入到 tbl_a 中
--   执行第三句, 因为没有指定的字段, 抛出ERROR, 程序中断执行.

接下来我们再看看事务是怎么处理的:

-- 在 phpMyAdmin 中执行下面的操作
-- 1, 建立支持事务的数据表 `tbl_b`
CREATE TABLE IF NOT EXISTS `tbl_b` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `val` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 ;

-- 2, 为 tbl_b 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行
begin; -- 开启一个事务
INSERT INTO tbl_b (val) VALUES ('a');
INSERT INTO tbl_b (val) VALUES ('b');
INSERT INTO tbl_b (vals) VALUES ('c'); -- 报错
INSERT INTO tbl_b (val) VALUES ('d');
commit;

-- 3, 我们来看看 tbl_b 中的数据, 会和 tbl_a 中的数据有什么差别呢?
SELECT * FROM tbl_b;
--   Empty set (0.00 sec)
--   一条数据也没有, 哈. 这就是事务与非事务的区别,
--   因为在事务中遇到了一个错误, 所整个事务中的 SQL 语句都不会对数据库构成实际影响

OK. 现在对事务有了形像的认识之后我们再来结合其它的例子进一步学习事务:

-- 在 phpMyAdmin 中执行下面的操作
-- 1, 清空 tbl_b 记录
TRUNCATE TABLE `tbl_b`

-- 2, 为 tbl_b 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行
-- begin; -- 注意没有执行 begin
INSERT INTO tbl_b (val) VALUES ('a');
INSERT INTO tbl_b (val) VALUES ('b');
INSERT INTO tbl_b (vals) VALUES ('c'); -- 报错
INSERT INTO tbl_b (val) VALUES ('d');
-- commit;

-- 3, 我们来看看 tbl_b 中的数据, 会和有执行 begin 的效果有什么差别?
SELECT * FROM tbl_b;
--   +----+-----+
--   | id | val |
--   +----+-----+
--   |  1 | a   |
--   |  2 | b   |
--   +----+-----+
--   有两条数据, 这是为什么?
--   因为事务数据表中的事务默认是自动提交的(AUTOCOMMIT), 它的执行过程是:
--   开启一个事务, 执行第一句, 没有ERROR, 提交事务, 对数据库产生实际影响, 将'a'真真实实的插入到 tbl_b 中
--   开启一个事务, 执行第二句, 没有ERROR, 提交事务, 对数据库产生实际影响, 将'b'真真实实的插入到 tbl_b 中
--   开启一个事务, 执行第三句, 因为没有指定的字段, 抛出ERROR, 程序中断执行.
--   这样明白了为什么要使用 begin 了吧, 换句话说,如果事务表中没有 begin,那它和非事务表执行的效果是一样的

下面是一个成功的例子:

-- 在 phpMyAdmin 中执行下面的操作
-- 1, 清空 tbl_b 记录
TRUNCATE TABLE `tbl_b`;

-- 2, 为 tbl_b 插入数据, 将下面 4 条语句全部复制, 用 phpMyAdmin 一并执行
begin;
INSERT INTO tbl_b (val) VALUES ('a');
INSERT INTO tbl_b (val) VALUES ('b');
INSERT INTO tbl_b (val) VALUES ('c');
INSERT INTO tbl_b (val) VALUES ('d');
-- rollback; -- roolback 可以理解为 un-commit, 不提交
commit; -- 注意最后要有 conmmit; 如果这有这一句会怎样? 动手试试吧.

-- 3, 我们来看看 tbl_b 中的数据, 四条数据成功插入.
SELECT * FROM tbl_b;

总结一下:
1, 在 Mysql 中要让数据表支持事务, 必须使用 InnoDB 或 BDB 数据引擎.
2, 事务数据表默认是 autocommit 的, 要开启一个事务应该使用 begin; 或者使用 SET AUTOCOMMIT={1|0} 来设置是否自动提交
3, 事务一定要 commit , 否则没有任何效果

原创粉丝点击