MyException - 我的异常网
当前位置:我的异常网» MySQL » MySQL (8)

MySQL (8)

www.MyException.Cn  网友分享于:2013-09-03  浏览:0次
MySQL (八)

1 事务

  • 需求:有一张银行账户表,A用户给B用户转账,A账户先减少,B账户增加,但是A操作完之后断电了。
  • 解决方案:A减少钱,但是不要立即修改数据表,B收到钱之后,同时修改数据表。

 

  • 事务:一系列要发生的连续的操作。
  • 事务安全:一种保护连续操作同时满足(实现)的机制,事务安全的意义:保证数据操作的完成性。

 

  • 示例SQL脚本
-- 创建一个账户表
CREATE TABLE my_account(
       id int primary key auto_increment,
    number CHAR(16) NOT NULL COMMENT '账户',
    NAME VARCHAR(20) NOT NULL COMMENT '姓名',
    money DECIMAL(10,2) DEFAULT 0.0 COMMENT '账户余额' 
);
-- 插入数据
INSERT INTO my_account VALUES (null,'0000000000000001','张三',1000);
INSERT INTO my_account VALUES (null,'0000000000000002','李四',2000);

-- 张三转账
UPDATE my_account SET money = money - 1000 WHERE NAME = '张三';

 

    • 张三一转完钱,就退出了系统,然后,可怕的是,李四没有收到,那么张三就少了这1000元,很可怕,如果天下银行都这么办,估计银行早就倒闭了。那怎么办,那就是要进行事务操作。  

 

 1.1 事务操作

  • 事务操作有两种:自动事务(默认的)和手动事务。

 

  •  手动事务:操作流程
    • ①开启事务(start transaction):告诉系统以下所有的操作(写)不要直接写入到数据库,先存放到事务日志。 

    • ②进行事务操作:一系列的操作(李四借钱给张三)。
      • 李四账户减少
-- 事务操作:1李四账户减少1000
UPDATE my_account SET money = money -1000 WHERE NAME = '李四';

SELECT * FROM my_account;

 我们在开启一个客户端,会发现如下的状况。

 

      • 张三账户增加    
-- 事务操纵:2张三账户增加1000
UPDATE my_account SET money = money +1000 WHERE NAME = '张三';
SELECT * FROM my_account;

我们如果再开启一个客户端,会发生如下状况

    • 关闭事务:选择性的将事务日志文件中的操作结果保存到数据表(同步)或直接清空事务日志(原来的操作全部清空)。
      • 提交事务(commit):同步数据表(操作成功)    
-- 提交事务
COMMIT;

当提交完事务的时候,我们会发现再开启一个客户端,两边的数据是一样的。

      • 回滚事务(rollback):直接清空日志表(操作失败)    

1.2 事务原理

  • 事务操作原理:事务开启之后,所有的操作都会临时保存到事务日志,事务日志只有在得到commit命令才会同步到数据库表,其它任何情况都会清空事务日志(rollback,断电,断开连接)。 

 

 

1.3  回滚点

  •  回滚点:在某个成功的操作完成之后,后续的操作有可能成功或失败,但是不管成功还是失败,前面的操作都已经成功;那么就可以在当前成功的位置,设置一个点,供后续失败操作返回到该位置,而不是返回所有操作,这个点就是回滚点。

 

  • 设置回滚点:savepoint 回滚点名字。
  • 回到回滚点:rollback to 回滚点名字。
-- 开启事务
START TRANSACTION;

-- 事务处理1:张三发工资
UPDATE my_account SET money = money + 10000 WHERE NAME = '张三';

-- 设置回滚点
SAVEPOINT sp1;

-- 银行扣税
UPDATE my_account SET money = money - 10000 * 0.5 WHERE NAME = '李四';

-- 回滚到回滚点
ROLLBACK TO sp1;

-- 继续给张三扣税
UPDATE my_account SET money = money - 10000 * 0.5 WHERE NAME = '张三';

-- 事务提交
COMMIT;

 

1.4 自动事务

  • 在MySQL中:默认的都是自动事务处理,用户操作完全会立即同步到数据表中。

 

  • 自动事务:系统通过autocommit的变量控制。
SHOW VARIABLES LIKE 'autocommit';

 

  •  关闭自动事务:set autocommit = off; 
SET autocommit = off;

  • 再次开启自动事务:set autocommit = on;

 

1.5 事务的特定(ACID)

  • 事务有四大特性:ACID
    • ①A:atomic,原子性,事务的整体是一个操作,不可分割,要么全部成功,要么全部失败。
    • ②C:consistency,一致性,事务操作的前后,事务表中的数据没有变化。
    • ③I:isolation,隔离性,事务操作是相互隔离不受影响的。
    • ④D:durability,持久性,数据一旦提交,不可该表,永久的改变数据表数据。  

 

  • 锁机制:innodb默认是行锁,但是如果在事务操作的过程中,没有使用到索引,那么系统会自动全表检索数据,自动升级为表锁。
    • 行锁:只有当前行被锁住,别的用户不能操作。
    • 表锁:整张表被锁住,别的用户不能操作。  

 

2 变量

  • 变量分为两种:系统变量和自定义变量。

 

2.1 系统变量

  • 系统变量:系统定义好的变量,大部分的时候用户根本不需要使用系统变量,系统变量是用来控制服务器的表现的,如autocommit等。

 

  • 查看系统变量
-- 查看所有系统变量
SHOW VARIABLES;
  • 查看具体的系统变量的值:select @@系统变量名;
select @@version,@@autocommit;

 

  • 修改系统变量
    • 修改系统变量分为两种:会话级别和全局级别
      • 会话级别:临时修改,当前客户端当次连接有效。    
set 变量 = 值;
      • 全局级别:一个修改,永久生效(多所有客户端都生效)    
set global 变量名 = 值;

 

2.2 自定义变量

  • 定义变量:
    • 系统为了区别是系统变量还是自定义变量,规定自定义变量前面必须加@  
set @变量 = 值;
    • 查看自定义变量  
slect @变量;

 

  • 在MySQL中,"="会默认的当做比较符号处理(很多地方),MySQL为了区分比较还是赋值的概念,重新定义了一个新的赋值符号: :=。当然,这个符号一般在SQL编程中使用。

 

  • MySQL允许从数据表中获取数据,然后赋值给变量,有两种方式。
    • ①边赋值,边查看结果  
select @变量名 := 字段名 from 数据源;-- 从字段中取值赋给变量名
    • ②只有赋值,没有结果,要求严格:数据记录最多只允许获取一条,MySQL不支持数组。  
select 字段名  from  数据源 [where 条件] into 变量列表
SELECT NAME FROM my_account WHERE id = 1 INTO @name;
SELECT @name;

 

  • 所有自定义变量都是会话级别:当前客户端当次连接有效。

3 触发器

  • 触发器:trigger,事先为某张表绑定好一段代码,当表中的某些内容发生改变的时候(增、删、改),系统会自动触发代码,执行。

 

  • 触犯器:事件类型、触发时间、触发对象。
    • 事件类型:增、删、改。
    • 触发时间:前后,before和after。
    • 触发对象:表中的每一条记录,针对行的。  

 

  • 一张表中只能有一种触发时间的一种类型的触发器,最多一张表有6个触发器。

 

3.1 创建触发器

 

  • 触发器基本语法:
-- 临时修改语句结束符
DELIMITER 自定义符号:后续代码中只有碰到自定义符号才算结束

CREATE TRIGGER 触发器名字 触发时间 事件类型 ON 表名 FOR EACH ROW
BEGIN -- 代表左大括号 开始

-- 里面就是触发器的内容:每行内容都必须使用;结束


END  -- 代表右大括号 结束
-- 语句结束符
自定义符号

-- 将邻水修改修正过来
DELIMITER ;

 

  • 示例脚本:
CREATE TABLE goods(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20) NOT NULL,
    price DECIMAL(10,2) DEFAULT 1,
    inv INT COMMENT '库存数量' 
);

INSERT INTO goods VALUES (NULL,'iphone6',2680,100);
INSERT INTO goods VALUES (NULL,'iphone6s',2880,100);

CREATE TABLE `order`(
    id INT PRIMARY KEY AUTO_INCREMENT,
    g_id INT NOT NULL COMMENT '商品id',
    g_number INT COMMENT '商品数量'
);

 

 

  • 创建触发器
-- 触发器:订单生成一个,商品库存减少一个
 -- 临时修改语句结束符
DELIMITER /
CREATE TRIGGER after_order AFTER INSERT ON `order` FOR EACH ROW
BEGIN
    UPDATE goods SET inv = inv -1 WHERE id = 2;

END
-- 结束触发器
/
-- 修改临时语句结束符
DELIMITER ;

 

3.2 查看触发器

  • 查看所有触发器或者模糊匹配
show triggers like 'pattern';

 

 

  •  查看触发器创建语句

 

show create trigger after_order;

 

  • 所有的触发器都会保存在information_schema.triggers表中。

 

3.3 使用触发器

  • 触发器:不需要手动调用,当某种情况发生的时候会自动触发。

 

  •  插入订单
SELECT * FROM goods;

INSERT INTO `order` VALUES (NULL,1,2);
SELECT * FROM goods;

    • ①触犯器的确工作了:订单生成了后,对应的商品表的商品数量减少了。②当前商品减少了,并不是订单中产生的商品;而是固定死的商品(触发器不合适)。  

 

 3.4 修改触发器&删除触发器

  • 触发器不能被修改,只能先删除,再新增新的触发器。
drop trigger 触发器名字;

 

3.5 触发器记录

  • 触发器记录:不管触发器是否触发了,只要当某种操作准备执行,系统就会将当前要操作记录的当前状态和即将执行之后新的状态给分别保留下来,供触发器使用。其中,要操作当前状态保存到old中,操作之后的可能状态保存给new。

  • old代表的是旧记录,new代表的是新记录。
    • 删除的时候是没有new的,而插入的时候是没有old的。  

 

  • old和new都是代表记录本身:任何一条记录除了有数据,还有字段名称
    • 使用方式:old.字段/new.字段。  
DELIMITER $$


CREATE
  
    TRIGGER `after_order` AFTER INSERT ON `order` 
    FOR EACH ROW BEGIN
    UPDATE goods SET inv = inv -new.g_number WHERE id = new.g_id;
END;
$$

DELIMITER ;
SELECT * FROM goods;

INSERT INTO `order` VALUES (NULL,1,2);

  • 如果触发器内部只有一条要执行的SQL指令,可以省略begin和end。 

 

  • 触发器:可以很好的协调表内部的数据处理顺序和关系,但是从java的角度出发,触发器会增加数据库维护的难度,所以较少使用触发器。

 

文章评论

十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
鲜为人知的编程真相
鲜为人知的编程真相
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
如何成为一名黑客
如何成为一名黑客
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
中美印日四国程序员比较
中美印日四国程序员比较
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
旅行,写作,编程
旅行,写作,编程
10个调试和排错的小建议
10个调试和排错的小建议
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员都该阅读的书
程序员都该阅读的书
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
漫画:程序员的工作
漫画:程序员的工作
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
Java程序员必看电影
Java程序员必看电影
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
我是如何打败拖延症的
我是如何打败拖延症的
为什么程序员都是夜猫子
为什么程序员都是夜猫子
程序员应该关注的一些事儿
程序员应该关注的一些事儿
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
编程语言是女人
编程语言是女人
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
老程序员的下场
老程序员的下场
程序员的鄙视链
程序员的鄙视链
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
代码女神横空出世
代码女神横空出世
每天工作4小时的程序员
每天工作4小时的程序员
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
那些争议最大的编程观点
那些争议最大的编程观点
程序员和编码员之间的区别
程序员和编码员之间的区别
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
一个程序员的时间管理
一个程序员的时间管理
 程序员的样子
程序员的样子
总结2014中国互联网十大段子
总结2014中国互联网十大段子
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有