# 事务操作
* 事务概念
> 事务(transaction):事务可以由一个或多个SQL语句组成,这写SQL语句是一个独立的单元,这个单元是一个整体是不可分割的。如果事务中的某一个语句执行失败,整个事务就会回滚到最初状态。因此,只有事务中所有语句都被执行成功,这个事务才会执行成功。
> 可以通过转账来理解事务,只有A成功转了,然后B成功收到了钱,才能算转账成功。当转成功,但是没有收到,应该将钱返回给A。
* 事务的ACID属性:
事务必须有ACID属性
原子性 Atomicity
一致性 Consistency
隔离性 Isolation 也叫孤立性
持久性 Durability
原子性: 原子型意味着意味着每个事务都必须被认为是一个不可分割的单元。整个事务中的所有操作,要么全部完成,要么全部不完成。
例如:买卖。只有买与卖都成功,才成功。不能说只有买或者只有卖
一致性: 事务必须始终保持系统处于一致的状态。
例如:对于买卖双方,当买卖失败了,双方就都应该一致认为失败了,当买卖成功了,双方都一致认为买卖成功了。
隔离性:每个事务对于数据库执行来说都是不可拆分的最小单元,所以每个事务都有着自己独立的副本,由数据库进行执行与操作。
例如:A与B的买卖,C与D的买卖互不干扰。
持久性:事务在运行成功之后,数据会持久保存到数据库上。
* 事务注意的问题
1. 只有innodb引擎支持事务
* mysql的事务处理语法
//开启一个事务
mysql> begin
//做保存点
mysql> savepoint 保存点名称
//事务回滚
mysql> rollback
或 回滚到某个保存点
mysql> rollback to 保存点名称
//事务确认
mysql> commit
写到begin与commit 或 begin与rollback之间的sql语句就是一个事务。
另外开启事务也可以使用 start transaction;
* 事务处理例子
1. 模拟银行转账
create table account(
id int primary key auto_increment,
uid int not null,
money decimal(19,2) not null default 0.00
)engine=innodb default charset=utf8;
//插入测试数据
insert into account(uid,money) values(3,1000);
insert into account(uid,money) values(8,2000);
//开启事务
mysql> begin;
mysql> update account set money=money-300 where uid=3;
//设置一个还原点
mysql> savepoint jian
mysql> update account set money=money+300 where uid=8;
//设置一个还原点
mysql> savepoint jia
//如果事务中的sql语句都执行成功就提交事务
mysql>commit;
或 如果事务中的sql语句只要有一条执行失败,就回滚
mysql> rollback;
# MySQL预处理
* 概念
预处理的意思是先提交sql语句到mysql服务端,执行预编译,客户端执行sql语句时,只需上传输入参数即可,这点和存储过程有点相似。
* 预处理工作原理
1. 预处理:创建 SQL 语句模板并发送到数据库。预留的值使用参数 "?" 标记 。例如:INSERT INTO MyGuests VALUES(?, ?, ?)
2. 数据库解析,编译,对SQL语句模板执行查询优化,并保存起来
3. 执行:最后,将应用绑定的值传递给参数("?" 标记),数据库执行语句。应用可以多次执行语句,如果参数的值不一样。
* 预处理优点
1. 预处理的执行效率相对于一般的sql执行操作,效率比较高,因为第二次执行只需要发送查询的参数,而不是整个语句
2. 预处理可以防止sql注入,因为预处理将sql语句与数据分开发送。
* 预处理语法
//新增一个预处理语句
prepare 预处理名称 from 'sql语句';
//执行预处理语句
execute 预处理名称 [ using @变量名 [, @变量名1 ] ...];
//删除预处理语句
drop prepare 预处理语句
* 预处理实例
1. 实例1
mysql> prepare stmt1 from 'select * from user';
mysql> execute stmt1;
//删除预处理语句
mysql> execute prepare stmt1;
2. 实例2
//?为占位符,代替将要传递进来的值
mysql> prepare stmt2 from 'select * from user where name=?';
mysql> set @n='jack';
//将变量@n的值传递给?
mysql> execute stmt2 using @n;
3. 实例3
mysql> prepare stmt3 from 'update user set name=? where id=?';
mysql> set @n='jack54',@id=1;
//将变量@n给到第一个?,@id给到第二个?
mysql> execute stmt3 using @n,@id;