mysql update语句的执行过程详解_Mysql

来源:脚本之家  责任编辑:小易  

mysql存储过程支持用表作为参数。 这个问题在MySQL 5.0以前非常麻烦,但是在MySQL 5.0.13版之后,由于引入了PREPARE语句,一切变得简单了。 例子如下(已验证): DROP PROCEDURE IF EXISTS `newtable`; CREATE PROCEDURE `newtable`(IN tname v

以前有过一篇关于MySQL查询语句的执行过程,这里总结一下update语句的执行过程。由于update涉及到数据的修改,所以,很容易推断,update语句比select语句会更复杂一些。

sql:update items set price = case id when 1 then 11.0 when 2 then 12.0 when 3 then 13.0 end, lowest = case id when 1 then 'jd' when 2 then 'tmall' when 3 then 'suning' end where id in (1, 2, 3). php的话,可以用数组来拼出类似上

1,准备

update 语句返回的数值 就是这条sql 影响了几行,就算数据表为空 也可以执行,语句本身没有错

创建一张test表

预制语句的SQL语法基于三个SQL语句: PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING @var_name [, @var_name] ]; {DEALLOCATE | DROP} PREPARE stmt_name; PREPARE语句用于预备一个语句,并赋予它名称stmt_name,借此在

CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `c` int(11) NOT NULL DEFAULT '0' COMMENT '数值', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='测试表';

SET id=Id; 这个语句,看起来很困惑. 搞不好这句话执行完了, = 啥事情没干。 UPDATE standard SET caoZuoMingCheng=czmc,biaoZhunShiJian=bzsj WHERE ID=id; 这里的条件是 WHERE 数据库的 ID 字段 = 变量id 有可能是前面的 id , 没有正确的赋值

插入三条数据

 立秋过后,暑热未尽,白天依旧炎热,虽然时有凉风起,但天气变化无常,早晚温差较大,三伏天中的末伏,依旧让人难忍。那该怎么样去应对比较好呢?三不睡一、不睡湿发觉头发不干睡觉易感冒引湿气,一天之中人的阳气在午夜的时候最弱的,人们经过一天的消耗,很容易感到疲惫,如果睡前用热水洗头后,已扩张的毛细血管,受到外界的刺激,头部的阳气遇到冷而凝时,就会使机体受到风寒。二、不带心事睡觉心事会扰乱睡眠,导致失眠,时间久了会导致神经衰弱甚至抑郁。且脾主运湿,思虑过重会损伤脾胃运化,脾一虚,无以运湿则湿气重。三、不睡过子时的觉中国人讲究夜半之前必睡,凡过子时还不睡,身体状况一定会越来越差,部分人一定会爆豆(也就是长

INSERT INTO `test` (`c`) VALUES (1), (2), (3);

聊文玩,找空空,关注南红讲堂头条号,学习文玩知识!成龙大哥60岁大寿时,宴请了娱乐圈中顶级重磅明星,可谁知当众多明星大咖到场时,竟被小叶紫檀手串抢了风头!甭管是娱乐圈还是文玩圈的人都熟知成龙是顶级紫檀收藏大家。当众多明星大咖参加成龙60岁寿宴时,成龙出手毫不吝啬,作为回礼,每位到场的明星都得到了一串高端品质的小叶紫檀佛珠手串。马云手持小叶紫檀手串,走起路来十分有气场。本山大叔可是圈中知名的佛珠手串发烧友啊,得此回礼,应该心情不错。鲁豫的小叶紫檀走秀~连老外明星也登场了,左手戴手表,右手戴小叶紫檀手串,原来时尚无国界!韩国诸多明星也来捧场,成龙大哥人缘很好嘛成龙60寿宴,宴请重磅明星,果然是被小

2,测试

首先自我介绍:作为一位90后,蛔虫可是儿时的噩梦,因为那时候不爱干净,肚子里的脏东西挺多,肚子老疼,小时候就吃打过蛔虫的药叫做宝塔糖。其次:现在没有几乎都没有蛔虫啦,因为啥呢,有下面五点。1卫生条件好了,蔬菜水果啥的都洗的很干净,饭前饭后洗手,时不时的洗手2各种保健食品吃着,严重破坏了身体内部组织调节3大量的污染源,蔬菜打农药,水果生长素,污水排放4大量的垃圾食品吃时间吃着5食品中的添加剂,什么瘦肉精呀,防腐剂呀,各种只有你想不到没有它做不到的添加剂这几点原因足以让蛔虫无路可逃。建议:要是有感觉自己肚子不舒服的话,可以去医院咨询一下医生,让医生开药方。最后:给大家讲一下儿时的吃蛔虫记忆。我记得

加入我要把第一条数据的 c 值 加 1,则

制作方法做法一食材准备文昌鸡(以将要下蛋的小母鸡最佳)1只(重约1千克左右)姜丝、蒜泥、味精、白醋、白糖、精盐、老抽各适量。制作步骤1:将活鸡割颈放血、去毛除脏(不损坏整鸡原状),洗净:在鸡素囊口插进一瓷汤勺(以利汤水从鸡腔中对流)把鸡脚扭反插进鸡下腹洞内固定:将鸡头仰屈,用翅膀窝夹住,(目的是使鸡头向后仰起、不用翅膀夹住亦可,但需在煮鸡时掌握好造型。)放进烧滚的清汤中翻转烫氽,使鸡身四周受热膨胀定型。2、改用慢火浸煮(以汤中冒气眼而不滚开为度)约5分钟,用铁勾将鸡提起,倒出腹腔汤水,再放入汤中浸煮,反复三、四次、至仅熟(不可大生也不可过熟),离火后另放凉汤中浸泡稍为冷却后取出,抹上一层香麻油

UPDATE `test` SET `c` = `c` + 1 WHERE `id` = 1;

按照我们平常的思路,就是找出这条记录,把它的值改好,保存就OK了。

但我们追究一下细节,由于涉及到修改数据,所以涉及到日志了。

3 操作顺序

3.1 查找记录:执行器先找引擎取id=1这一行。ID是主键,引擎直接用树搜索找到这一行。如果id=1这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回;

3.2 执行器拿到引擎返回的行数据,把num改为2,得到新的一行数据,再调用引擎接口写入这行新数据;

3.3 引擎将这行新数据更新到内存中,同时将这个更新操作记录到redo log里面,此时redo log处于prepare状态;

3.4 引擎告知执行器,我执行完成了,你随时可以调我的接口提交事务了;

3.5 执行器生成这个操作的binlog,并把binlog写入磁盘。

3.6 执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交commit状态,更新完成。

binlog是MySQL内部实现二阶段提交协调者,它为每个事务分配一个事务ID: XID

一阶段

开启事务,redo log 和 undo log已经记录了对应的日志,此时事务状态为prepare

二阶段

binlog 完成write和fsync后,成功,事务一定提交了,否则事务回滚 发送commit,清除undo信息,刷redo,设置事务状态为completed

  4, 两种日志 4.1 重做日志 redo log

redo log 通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。

一般更新会有如下做法:

直接查询原始数据,立马更新; 先找个临时记事本,做下记录,等不忙的时候/结算时候进行核算更新。

第一种做法在高并发IO的情况下非常的不容乐观。所以一般都会采用第二种方式。

同样在MySQL里存在这样的一个问题,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程IO成本、查找成本都很高。为了解决这个问题,MySQL的设计者就用了redo log的思路来提升更新效率。

临时记事本和原始数据进行操作的整个过程,也是对应MySQL里经常说到的WAL(预写式日志)技术WAL的全称是Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。具体来说,当有一条记录需要更新的时候,InnoDB引擎就会先把记录写到redo log(记事本)里面,并更新内存,这个时候更新就算完成了。同时,InnoDB引擎会在适当的时候,将这个记事本里的操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

问题:redo log(记事本)写满如何解决?

InnoDB的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么这块“记事本”总共就可以记录4GB的操作。从头开始写,写到末尾就又回到开头循环写,如下面这个图所示。

write pos是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

write pos和checkpoint之间的是“记事本”上还空着的部分,可以用来记录新的操作。如果write pos追上checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把checkpoint推进一下。

有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe

4.2 归档日志 binlog

MySQL整体来看,其实就有两块:一块是Server层,它主要做的是MySQL功能层面的事情;还有一块是引擎层,负责存储相关的具体事宜。上面redo log是InnoDB引擎特有的日志,而Server层也有自己的日志,称为binlog(归档日志)。

为什么会有两份日志呢?

最开始MySQL里并没有InnoDB引擎。MySQL自带的引擎是MyISAM,但是MyISAM没有crash-safe的能力,binlog日志只能用于归档。而InnoDB是另一个公司以插件形式引入MySQL的,既然只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统——也就是redo log来实现crash-safe能力。

这两种日志有以下三点不同。

redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。

redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。

redo log是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

5 两阶段提交

将redo log的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。

5.1 为什么必须有“两阶段提交”呢?这是为了让两份日志之间的逻辑一致。

binlog会记录所有的逻辑操作,并且是采用“追加写”的形式。如果你的DBA承诺说半个月内可以恢复,那么备份系统中一定会保存最近半个月的所有binlog,同时系统会定期做整库备份。这里的“定期”取决于系统的重要性,可以是一天一备,也可以是一周一备。

当需要恢复到指定的某一秒时,比如某天下午两点发现中午十二点有一次误删表,需要找回数据,那你可以这么做:

首先,找到最近的一次全量备份,如果你运气好,可能就是昨天晚上的一个备份,从这个备份恢复到临时库;

然后,从备份的时间点开始,将备份的binlog依次取出来,重放到中午误删表之前的那个时刻。

这样你的临时库就跟误删之前的线上库一样了,然后你可以把表数据从临时库取出来,按需要恢复到线上库去。

说完了数据恢复过程,我们回来说说,为什么日志需要“两阶段提交”。这里不妨用反证法来进行解释。

5.2 如果不用两阶段提交

由于redo log和binlog是两个独立的逻辑,如果不用两阶段提交,要么就是先写完redo log再写binlog,或者采用反过来的顺序。

我们看看这两种方式会有什么问题。

仍然用前面的update语句来做例子,当前ID=1的行,字段c的值是1。

5.2.1 先写redo log,后写binlog

假设在redo log写完了,但binlog还没有写完的时候,MySQL进程异常重启。由于我们前面说过的,redo log写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行c的值是2。但是由于binlog没写完就crash了,这时候binlog里面就没有记录这个语句,如果需要用这个binlog来恢复临时库的话,由于这个语句的binlog丢失,这个临时库就会少了这一次更新,恢复出来的这一行c的值就是1,与原库的值不同。

5.2.2 先写binlog,后写redo log

如果在binlog写完之后crash,由于redo log还没写,崩溃恢复以后这个事务无效,所以这一行c的值是1。但是binlog里面已经记录了“把c从1改成2”这个日志。所以,在之后用binlog来恢复的时候,恢复出来的临时库中的这一行c值就是2,与原库的值不同。

可以看到,如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。

其实不只是误操作后需要用这个过程来恢复数据。当需要扩容的时候,也就是需要再多搭建一些备库来增加系统的读能力的时候,现在常见的做法也是用全量备份加上应用binlog来实现的,这个“不一致”就会导致你的线上出现主从数据库不一致的情况。

简单说,redo log和binlog都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。

redo log 用于保证crash-safe能力。innodb_flush_log_at_trx_commit这个参数设置成1的时候,表示每次事务的redo log都直接持久化到磁盘。这个参数建议设置成1,这样可以保证MySQL异常重启之后数据不丢失。

sync_binlog 这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。这个参数也建议设置成1,这样可以保证MySQL异常重启之后binlog不丢失。

以上就是mysql update语句的执行过程详解的详细内容,更多关于update语句的执行过程的资料请关注真格学网其它相关文章!

扩展阅读,根据您访问的内容系统为您准备了以下内容,希望对您有帮助。

mysql执行update语句的问题

update tb_permission SET pageurl=null where id=2

请注意

1. 没有 关键字 From

2. 不是 is null 而是 = null

mysql update 语句有没有可能只执行一半,示例如下:

自然不可能,,,,

update 的执行顺序是:从左到右,变量优先,逐行更新.(忘记从哪看的这句话了,,,,)更多追问追答追问可是为什么我的网站程序中出现了这样的情况?

我也感觉不大可能的,好郁闷追答你可以跟踪下执行计划,看执行计划中是否有回滚的现象追问执行计划?你是说程序中有没有返回之前状态的操作,还是说mysql 中是不是 回滚 ?

还望不吝赐教啊追答只从数据库来说,看mysql 中是不是 回滚

mysql有办法判断一个update语句执行后数据是否真的有变化么

查看数据是否有变化也要看你做的更新操作是否和源数据是否相同,只有先查出来做比对,如果一样可以不进行更新,只有这样。本回答被提问者采纳

mysql中一个update语句如何去写

首先,单表的UPDATE语句:

UPDATE [LOW_PRIORITY] [IGNORE] tbl_name

SET col_name1=expr1 [, col_name2=expr2 ...]

[WHERE where_definition]

[ORDER BY ...]

[LIMIT row_count]

其次,多表的UPDATE语句:

UPDATE [LOW_PRIORITY] [IGNORE] table_references

SET col_name1=expr1 [, col_name2=expr2 ...]

[WHERE where_definition]

UPDATE语法可以用新值更新原有表行中的各列。

SET子句指示要修改哪些列和要给予哪些值。WHERE子句指定应更新哪些行。

如果没有WHERE子句,则更新所有的行。如果指定了ORDER BY子句,则按照被指定的顺序对行进行更新。

LIMIT子句用于给定一个限值,*可以被更新的行的数目。

UPDATE语句支持以下修饰符:

1,如果您使用LOW_PRIORITY关键词,则UPDATE的执行被延迟了,直到没有其它的客户端从表中读取为止。

2,如果您使用IGNORE关键词,则即使在更新过程中出现错误,更新语句也不会中断。

如果出现了重复关键字冲突,则这些行不会被更新。如果列被更新后,新值会导致数据转化错误,则这些行被更新为最接近的合法的值。

如果您在一个表达式中通过tbl_name访问一列,则UPDATE使用列中的当前值。

例如,把年龄列设置为比当前值多一:

代码如下:

mysql> UPDATE persondata SET age=age+1;

UPDATE赋值被从左到右评估。

例如,对年龄列加倍,然后再进行增加:

代码如下:

mysql> UPDATE persondata SET age=age*2, age=age+1;

如果您把一列设置为其当前含有的值,则MySQL会注意到这一点,但不会更新。

如果您把被已定义为NOT NULL的列更新为NULL,则该列被设置到与列类型对应的默认值,并且累加警告数。

对于数字类型,默认值为0;对于字符串类型,默认值为空字符串('');对于日期和时间类型,默认值为“zero”值。

UPDATE会返回实际被改变的行的数目。Mysql_info() C API函数可以返回被匹配和被更新的行的数目,以及在UPDATE过程中产生的警告的数量。

您可以使用LIMIT row_count来限定UPDATE的范围。LIMIT子句是一个与行匹配的限定。

只要发现可以满足WHERE子句的row_count行,则该语句中止,不论这些行是否被改变。

如果一个UPDATE语句包括一个ORDER BY子句,则按照由子句指定的顺序更新行。

您也可以执行包括多个表的UPDATE操作。table_references子句列出了在联合中包含的表。

例子:

代码如下:

SQL>UPDATE items,month SET items.price=month.price

WHERE items.id=month.id;

说明:以上代码显示出了使用逗号操作符的内部联合,但是multiple-table UPDATE语句可以使用在SELECT语句中允许的任何类型的联合,比如LEFT JOIN。

注释:不能把ORDER BY或LIMIT与multiple-table UPDATE同时使用。

在一个被更改的multiple-table UPDATE中,有些列被引用。您只需要这些列的UPDATE权限。有些列被读取了,但是没被修改。您只需要这些列的SELECT权限。

如果您使用的multiple-table UPDATE语句中包含带有外键*的InnoDB表,则MySQL优化符处理表的顺序可能与上下层级关系的顺序不同。

在此情况下,语句无效并被 回滚。同时,更新一个单一表,并且依靠ON UPDATE功能。

该功能由InnoDB提供,用于对其它表进行相应的修改。

目前,不能在一个子查询中更新一个表,同时从同一个表中选择。

update语句的几种基本用法

A. 使用简单的 UPDATE

下列示例说明如果从 UPDATE 语句中去除 WHERE 子句,所有的行会受到什么影响。

下面这个例子说明,如果表 publishers 中的所有出版社将总部搬迁到佐治亚州的亚特兰大市,表 publishers 如何更新。

代码如下:

UPDATE publishers

SET city = 'Atlanta', state = 'GA'

本示例将所有出版商的名字变为 NULL。

复制代码 代码如下:

UPDATE publishers

SET pub_name = NULL

也可以在更新中使用计算值。本示例将表 titles 中的所有价格加倍。

代码如下:

UPDATE titles

SET price = price * 2

B.把 WHERE 子句和 UPDATE 语句一起使用

WHERE 子句指定要更新的行例如,在下面这个虚构的事件中,北加利福尼亚更名为 Pacifica(缩写为 PC),而奥克兰的市民投票决定将其城市的名字改为 Bay City。这个例子说明如何为奥克兰市以前的所有居民(他们的地址已经过时)更新表 authors。

代码如下:

UPDATE authors

SET state = 'PC', city = 'Bay City'

WHERE state = 'CA' AND city = 'Oakland'

必须编写另一个语句来更改北加利福尼亚其它城市的居民所在的州名。

C.通过 UPDATE 语句使用来自另一个表的信息

本示例修改表 titles 中的 ytd_sales 列,以反映表 sales 中的最新销售记录。

复制代码 代码如下:

UPDATE titles

SET ytd_sales = titles.ytd_sales + sales.qty

FROM titles, sales

WHERE titles.title_id = sales.title_id

AND sales.ord_date = (SELECT MAX(sales.ord_date) FROM sales)

这个例子假定,一种特定的商品在特定的日期只记录一批销售量,而且更新是最新的。如果不是这样(即如果一种特定的商品在同一天可以记录不止一批销售量),这里所示的例子将出错。例子可正确执行,但是每种商品只用一批销售量进行更新,而不管那一天实际销售了多少批。这是因为一个 UPDATE 语句从不会对同一行更新两次。

对于特定的商品在同一天可销售不止一批的情况,每种商品的所有销售量必须在 UPDATE 语句中合计在一起,如下例所示:

代码如下:

UPDATE titles

SET ytd_sales =

(SELECT SUM(qty)

FROM sales

WHERE sales.title_id = titles.title_id

AND sales.ord_date IN (SELECT MAX(ord_date) FROM sales))

FROM titles, sales

D. 将 UPDATE 语句与 SELECT 语句中的 TOP 子句一起使用

这个例子对来自表 authors 的前十个作者的 state 列进行更新。

代码如下:

UPDATE authors

SET state = 'ZZ'

FROM (SELECT TOP 10 * FROM authors ORDER BY au_lname) AS t1

WHERE authors.au_id = t1.au_id

以上就是mysql update语句用法的全部内容

  • 本文相关:
  • oracle执行update语句时卡住问题分析及解决办法
  • mybatis执行批量更新batch update 的方法(oracle,mysql两种)
  • 解决hibernate4执行save()或update()无效问题的方法
  • php+mysql判断update语句是否执行成功的方法
  • 执行一条sql语句update多条记录实现思路
  • mysql 5.7.11 winx64.zip安装配置方法图文教程
  • linux下centos7安装mysql5.7.19的详细教程
  • windows 下noinstall方式安装 mysql 5.7.5 m15 winx64(推荐)
  • mysql修改默认存储引擎的实现方法
  • mysql实现当前数据表的所有时间都增加或减少指定的时间间隔(推荐
  • mysql中group_concat函数深入理解
  • mysql 备份与迁移 数据同步方法
  • centos7 移动mysql5.7.19 数据存储位置的操作方法
  • mysql闪退和服务无法启动的解决方法
  • mysql字段自增自减的sql语句示例介绍
  • mysql执行update语句的问题
  • mysql update 语句有没有可能只执行一半,示例如下:
  • mysql有办法判断一个update语句执行后数据是否真的...
  • mysql中一个update语句如何去写
  • mysql 存储过程 执行多条update sql
  • Mysql 存储过程 UPDATE语句 字段=传递过来的参数字...
  • MySQL频繁执行update语句会卡死表,求教如何优化
  • mysql里边用update修改没有的数据也会执行成功
  • MYSQL如何执行动态过程.
  • mysql的UPDATE语句,程序没报错,但没生效。求高手...
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全mssqlmysqlmariadboracledb2mssql2008mssql2005sqlitepostgresqlmongodbredisaccess数据库文摘数据库其它首页mysqloracle执行update语句时卡住问题分析及解决办法mybatis执行批量更新batch update 的方法(oracle,mysql两种)解决hibernate4执行save()或update()无效问题的方法php+mysql判断update语句是否执行成功的方法执行一条sql语句update多条记录实现思路mysql 5.7.11 winx64.zip安装配置方法图文教程linux下centos7安装mysql5.7.19的详细教程windows 下noinstall方式安装 mysql 5.7.5 m15 winx64(推荐)mysql修改默认存储引擎的实现方法mysql实现当前数据表的所有时间都增加或减少指定的时间间隔(推荐mysql中group_concat函数深入理解mysql 备份与迁移 数据同步方法centos7 移动mysql5.7.19 数据存储位置的操作方法mysql闪退和服务无法启动的解决方法mysql字段自增自减的sql语句示例介绍mysql安装图解 mysql图文安装教程can""t connect to mysql serverwindows下mysql5.6版本安装及配置mysql字符串截取函数substring的mysql创建用户与授权方法mysql提示:the server quit withmysql日期数据类型、时间类型使用mysql——修改root密码的4种方法mysql update语句的用法详解mysql 的case when 语句使用说明解决mysql输入密码闪退的问题mysql性能优化的最佳20+条经验用shell写一个mysql数据备份脚本mysql常用查询命令操作大全centos6.7 mysql5.6.33修改数据文件位置的mysql如何在已有数据库上统一字符集mysql 自定义函数create function示例mysql 8.0.12 winx64详细安装教程mysql中字符串与num类型拼接报错的解决方免安转mysql服务的启动与停止方法
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved