首页 > 技术文章 > MySQL预处理和事务

onlyzc 2018-02-05 12:11 原文

# 事务操作

* 事务概念

> 事务(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;

 

推荐阅读