mysql同步三张表如何用事务_MySQL 多表查询与事务的操作

这篇博客详细介绍了MySQL中的多表查询,包括内连接、左外连接、右外连接和子查询的使用,以及事务的概念、应用场景、手动提交和自动提交事务的流程。还探讨了事务的隔离级别及其解决并发访问问题的方法,并讲解了DCL(Data Control Language),涉及用户创建、权限赋予、撤销及修改等操作。
摘要由CSDN通过智能技术生成

表连接查询

什么是多表查询

# 数据准备

6d2077c234f3118094fbf746d27fd555.png

1c5312925b96ed436ce1cb22c86e69ae.png

# 多表查询的作用

* 比如:我们想查询孙悟空的名字和他所在的部门的名字,则需要使用多表查询

# 如果一条 SQL 语句查询多张表,因为查询结果在多张不同的表中,每张表取 1 列或多列

# 多表查询的分类

754f630ba2fb9d8f75ed1ba9ef28ed3e.png

笛卡尔积现象

# 什么是笛卡尔积现象?

389e9b30ecc643ecf7749177e18464ee.png

14cb46c8f1feacec254b2e444d27a4bd.png

# 如何消除笛卡尔积现象的影响

* 我们发现不是所有的数据组合都是有用的,只有员工表.dept_id = 部门表.id 的数据才是有用的。所以需要通过条件过滤掉没用的数据

30dd2272c1c9ee759a1a998205c40801.png

内连接

用左边表的记录去匹配右边表的记录,如果符合条件的则显示。如:从表.外键 = 主表.主键

# 隐式内连接

* 看不到 JOIN 关键字,条件使用 WHERE 指定

9d11a0dadd5aee761c1bcdff2023d67c.png

f62609c63ce25d2dd409a94cb983fd7d.png

# 显示内连接

* 使用 INNER JOIN ... ON 语句,可以省略 INNER

c3e8f92fa5b2175a2f75e6f84eb767ab.png

# 内连接查询的步骤:

* 确定查询哪些表

* 确定表连接的条件

* 确定查询的条件

* 确定查询的字段

左外连接

# 使用 LEFT OUTER JOIN ... ON 语句,OUTER 可以省略

2a609d1d7fae76c321e5ec6b6e7ac49b.png

* 用左表的记录去匹配右边表的记录,如果符合条件的则显示,否则,显示 NULL

* 可以理解为:在内连接的基础上保证坐标的数据全部显示

963eb959becf3f6070be13317cf544f4.png

fa09fcdeb7826c660c7fbeff8bc81c8b.png

右外连接

# 使用 RIGHT OUTER JOIN ... ON 语句,OUTER 可以省略

ea7e49ce4a97319bc3847bc104fcd8a1.png

* 用右边表的记录去匹配左边表的记录,如果符合条件的则显示

* 可以理解为:在内连接的基础上保证右表的数据全部显示

d476920055a5a21256c96b8f23d9ef18.png

子查询

什么是子查询

c92da97fdaa7715a6dff56b73d9dbf7a.png

2854b0cd31387c759b284b2730b512ac.png

# 子查询的概念:

* 一个查询的结果作为另一个查询的条件

* 有查询的嵌套,内部的查询称为子查询

* 子查询要用括号

子查询结果的三种情况

# 子查询的结果是单行单列的

3e95b0e10377bbff608c110399017dc7.png

# 子查询的结果是多行单列的

6e67e1f262531466166cddececdc0681.png

# 子查询的结果是多行多列的

6d6c5dc73dd2a869eb8cf11c521afbdc.png

子查询的结果是一个值的时候

# 子查询的结果只要是单行单列,肯定在 WHERE 后面作为条件,父查询一般使用比较运算符

6f2c91fa4f79d5303edf7b0fe6723e2a.png

# 案例:查询工资最高的员工是谁

96c4ce91ef563c0c43d5c25ca6a3121a.png

# 案例:查询工资低于平均工资的员工有哪些

07af8bebaf0f96c716540cc9c3d30d11.png

子查询的结果是多行单列的时候

# 子查询的结果是单列多行,结果集类似于一个数组,父查询使用 IN 运算符。

a8f55b0478f538830f2c100763f01f88.png

# 案例:查询工资大于 5000 的员工来自哪些部门

135cb54d6d19fb2aca533802f6c331ac.png

# 案例:查询开发部与财务部所有的员工信息

bde6bc029c8afc908c627210e9251f0b.png

子查询的结果是多行多列的

# 子查询的结果只要是多列的,肯定在 FROM 后面作为表

152c6a8c0e669952a723d5c9bf9ac5d5.png

* 子查询作为表需要取别名,否则这张表没有名称则无法访问表中的字段

# 案例:查询 2011 年后入职的员工信息,包括部门名称

0bb6c20e9be0024d67eee8ca04019f5c.png

* 使用表连接完成

bf32e48094f0c19e59dbbacd1b249b2f.png

子查询小结

# 子查询结果只要是单列,则在 WHERE 后面作为条件

# 子查询结果只要是多列,则在 FROM 后面作为表进行二次查询

事务

事务的应用场景说明

# 什么是事务:在实际的开发过程中,一个业务操作如:转账,往往是要多次访问数据库才能完成的。转账是一个用户扣钱,另一个用户加钱。如果其中有一条 SQL 语句出现异常,这条 SQL 语句可能执行失败。

# 事务的执行是一个整体,所有的 SQL 语句都必须执行成功。如果其中有一条 SQL 语句出现异常,则所有的 SQL 语句都要回滚,整个业务执行失败。

# 转账操作

f8709b008041daa81d00bba1c0c256f5.png

* 模拟张三给李四转 500 元钱,一个转账业务至少要执行下面的 2 条语句:

* 张三账号 - 500

* 李四账号 + 500

fe49948c2ee6035f739f8155292cfe86.png

* 假设当张三账号上 -500 元操作发生后,服务器立刻崩溃了,李四的账户并没有 +500,那么此时数据就出现问题了。

手动提交事务

# MySQL 中可以有两种方式进行事务的操作:

* 手动提交事务

* 自动提交事务

# 手动提交事务的 SQL 语句

6dfbaff2996ebf394f9b503e91a081ed.png

# 手动提交事务使用过程

* 执行成功的情况:开启事务 -> 执行多条 SQL 语句 -> 成功提交事务

* 执行失败的情况:开启事务 -> 执行多条 SQL 语句 -> 事务的回滚

b845c4b904c0d5f4a1c5d631c514837c.png

# 案例演示:事务提交

* 模拟张三给李四成功转账 500 元钱

e4f57bdcbe901ff162b8a715f6540bf4.png

1) 使用 DOS 控制台进入 MySQL

2) 执行以下 SQL 语句: 1.开启事务, 2.张三账号-500, 3.李四账号+500

3) 使用 SQLYog 查看数据库:发现数据并没有改变

4) 在控制台执行 commit 提交事务

5) 使用 SQLYog 查看数据库:发现数据改变

45ff970fa90b508fb9e60a8ffa9cc8a7.png

# 案例演示:事务回滚

* 模拟张三给李四失败地转账 500 元钱

376d902bb2d36adefcfc4094fabdaa82.png

1) 在控制台执行以下 SQL 语句:1.开启事务, 2.张三账号-500

2) 使用 SQLYog 查看数据库:发现数据并没有改变

3) 在控制台执行 rollback 回滚事务:

4) 使用 SQLYog 查看数据库:发现数据没有改变

58a27589df5f44939bd253307cdfb541.png

* 总结:如果事务中 SQL 语句没有问题,commit 提交事务,会对数据库的数据进行改变。如果事务中 SQL 语句有问题,rollback 回滚事务,会回退到开启事务时的状态

自动提交事务

# MySQL 默认每一条 DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,语句执行完毕自动提交事务

c1790b9e65b2d9e38966d4341dc226be.png

# 案例演示:自动提交事务

1) 将金额重置为 1000

2) 更新其中某一个账户

3) 使用 SQLyog 查看数据库:发现数据已经改变

dfe0b988208767814cea1a1fdbfd1a64.png

# 取消自动提交

* 查看 MySQL 是否开启自动提交事务

1192f622f5e84edc681c68aed783805a.png

@@表示全局变量,1 表示开启,0 表示关闭

* 取消自动提交事务

c4913fe0f4cd3e80da4833746e413cdb.png

* 执行更新语句,使用 SQLyog 查看数据库,发现数据并没有改变

* 在控制台执行 commit 提交任务

7bd3ad433e412758b497559e280a2117.png

事务原理

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

# 原理图

29d1250d08854d6e9faf5cae91a2947f.png

# 事务的步骤

* 客户端连接数据库服务器,创建连接时创建此用户临时日志文件

* 开启事务以后,所有的操作都会先写入到哦临时日志文件中

* 所有的查询操作从表中查询,但会经过日志文件加功后才返回

* 如果事务提交则将日志文件中的数据写到表中,否则清空日志文件

回滚点

# 什么是回滚点

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

# 回滚点的操作语句

e71ed43c7c1edeb039e1de9fdc90bdff.png

# 具体操作

1)将数据还原到 1000

2)开启事务

3)让张三账号减3次钱,每次10块

4)设置回滚点:savepoint three_times;

5)让张三账号减4次钱,每次10块

6)回到回滚点:rollback to three_times;

7)分析执行过程

# 总结:设置回滚点可以让我们在失败的时候回到回滚点,而不是回到事务开启的时候

事务的隔离级别

# 事务的四大特性 ACID

53b9d39aa30a558875ea8506662f70e6.png

# 并发访问的问题

* 事务在操作时的理想状态:所有的事务之间保持隔离,互不影响。因为并发操作,多个用户同时访问同一个数据可能引发并发访问的问题:

a6f426a4838053e525c4c7be04a56499.png

# MySQL 数据库有四种隔离级别

* 上面的级别最低,下面的级别最高。

5dbed742a7e007f6046818087df5c895.png

* 隔离级别越高,性能越差,安全性越高。

# MySQL 事务隔离级别相关的命令

* 查询全局事务隔离级别

46c8d210c6b3ea2b0377c5908f21012e.png

* 设置事务隔离级别,需要退出 MySQL 再重新登录才能看到隔离级别的变化

f6ec1d187d6530d4630ae5aaff92e06d.png

# 脏读 的演示

* 将数据进行恢复:UPDATE account SET balance = 1000;

1)打开 A 窗口登录 MySQL,设置全局的隔离级别为最低

f92c7267f48436ccb94382d55d456adb.png

31ec21fd65fba270abc3e499aaa76c67.png

2)打开 B 窗口,A B 窗口都开启事务

b1df3d96a60d3ea4880eac64a7f8f5a6.png

c83f3e845d44b60ba897cf6479348a4c.png

3)A 窗口更新 2 个人的账户数据,未提交

282f67acbfc97096caffef5c2c90406d.png

fa972658405bb69fc563cea69d169e39.png

4)B 窗口查询账户

194549dd484fa73f5f1905153887ec00.png

3ca65c594257fb401e600e0c79c904d3.png

5)A 窗口回滚

f1e7b5c9e0acfb87cc8f050c574f538f.png

db3779880b0fd2f3fd15cbe03e1e0dbc.png

6) B 窗口查询账户,钱没了

bd70cadda9eb411653a39045bd8a89e7.png

# 解决脏读的问题:将全局的隔离级别升级为 read committed

* 将数据进行恢复:UPDATE account SET balance = 1000;

1)在 A 窗口设置全局的隔离级别为 read committed

14c950600508957b1749b78c6c46b4b7.png

3ba1650d5d830957fdf04c31f778c3e0.png

2)B 窗口重新登录 MySQL

fb895bd2804f9bf72f37a4bb05abc1f5.png

3) 在 A B 窗口同时开启事务

cc44c56a49ca0ae2b5e392ce2cff6408.png

4)A 更新 2 个人的账户,未提交

8906f0d0d791c1c4de416c557204896a.png

b10f8b2c298639c3dd88a1ea57e2d55a.png

5)B 窗口查询账户

3b9f14499fdd9e1bd0633ae90633360a.png

6)A 窗口 commit 提交事务

4f7081cd2100431a42d3a5de80984582.png

7)B 窗口查看账户

851df8dba946c9bf4608fd3803beb9bc.png

* 结论:read committed 的方式可以避免脏读的发生

# 不可重复读的演示

* 将数据进行恢复:UPDATE account SET balance = 1000;

1)开启 A 窗口

1bc33b5b0c986ef18b067be827c4b2ce.png

6062882d82f30e18a459e1d4d1d0e1bb.png

2)开启 B 窗口,在 B 窗口开启事务

43f6c7f9af0cb6f723cf1610c6055102.png

db346c5688f3ee87800d3eeb83dfb988.png

3)在 A 窗口开启事务,并更新数据

7617b0b14941b7475bda52c08f7b8325.png

40e5f7fb5198967f246b6372599511d8.png

4)B 窗口查询

640c6a76febc613d67ea0f5e4ce08c24.png

b33a3cafbeb9a1a79fd22af5284d0407.png

# 解决不可重复的读的问题:将隔离级别提升为 repeatable read

* 将数据进行恢复:UPDATE account SET balance = 1000;

1)A 窗口设置隔离级别为:repeatable read

fa2aba37e05fef33a76257ed4d36ca58.png

31ac5a2cfa5caf627c66e9117a09fcee.png

2)B 窗口退出 MySQL,B 窗口再进入 MySQL

aba015461c010080e3d0d2e9d174ea82.png

45da0bc0675e40514f3f2fb39869dc1f.png

3)A 窗口更新数据

5dc5678c551d9a85c8f7b8f225e53efd.png

f90f619118c4699ee0af506a7e8f326e.png

4)B 窗口查询

143de5ba98592e8666a3c8bfd611d366.png

fa4e5a193c21640f8adf4f412a67f2e6.png

* 结论:统一个事务中为了保证多次查询数据一致,必须使用 repeatable read 隔离

fe9088ceda3a4b0086603a9c767a74fc.png

# 幻读 的演示

* 在 MySQL 中无法看到幻读的效果,但我们可以将事务隔离级别设置到最高,以挡住幻读的发生,将数据进行恢复

* 将数据进行恢复:UPDATE account SET balance = 1000;

1)开启 A 窗口

02019a99bf5657a40fb73657e5838c89.png

e3b65f968a3e7f413b0862d002b02dcb.png

2)A 窗口退出 MySQL,A 窗口重新登录 MySQL

f61d3852b98cdb3c4b93148a9559cf03.png

b358294dc6ea651e29103957e421a639.png

3)再开启 B 窗口,登录 MySQL

4)在 B 窗口中开启事务,添加一条记录

ec0fe352302499aa11f65d73b0bcb8b0.png

46e6114c893d7a44e91abfe41b69f802.png

5)在 A 窗口中 commit 提交事务,B 窗口中的 insert 语句会在 A 窗口事务提交后马上运行

f02d3cd544de0fa75b1c40cc43e4fc3e.png

6)在 A 窗口中接着查询,发现数据不变

4aac9b46c104f137cdd6db606db52421.png

c7ed61c23b764248cade75c9c932352f.png

7)B 窗口中 commit 提交当前事务

acbd38baeac38e92f66775fe733d5cb2.png

8)A 窗口就能看到最新的数据

616bc23633c9a6791e575bb990baa723.png

* 结论:使用 serializable 隔离级别,一个事务没有执行完,其他事务的 SQL 执行不了,可以挡住幻读

DCL(Data Control Language)

创建用户

# 语法

* CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';

# 关键字说明

28cb102fe0230c5c2788afc9e28386db.png

# 具体操作

* 创建 user1 用户,只能在 localhost 这个服务器登录 mysql 服务器,密码为 123

2ac74ca6b1e58e70057c3588f93b3620.png

* 创建 user2 用户,可以在任何电脑上登录 mysql 服务器,密码为123

dad1cd376a51e3b9f3a3411139314cb3.png

# 创建的用户名都在 mysql 数据库中的 user 表中可以查看到,密码经过加密

669499947fd85ef55787a0e5cd30b141.png

给用户授权

# 语法:

* GRANT 权限1,权限2,... ON 数据库.数据表 TO ‘用户名’@‘主机名’;

# 关键字说明

4b69488880187dbfd346c797e9db7c2a.png

# 具体操作:

* 给 user1 用户分配对 test 这个数据库操作的权限:创建表,修改表,插入记录,更新记录,查询

c915fc6405ab7ba449b5c7a636e2b691.png

* 给 user2 用户分配所有权限,对所有数据库的所有表

497ab61d57e1131a2930018a94f7d907.png

撤销权限

# 语法:

* REVOKE 权限1,权限2,... ON 数据库.表名 FROM '用户名'@'主机名';

# 关键字说明

069c325227e6d2af0e7685cd64c872c5.png

# 具体操作

* 撤销 user1 用户对 test 数据库所有表的操作权限

13eec41536735b4c9cf363006eb4d1c2.png

查看权限

# 语法:

* SHOW GRANTS FOR '用户名'@'主机名';

# 具体操作:

* 查看 user1 用户的权限

b4a5d814459b1d9121a4f337d18b70bc.png

# usage 是指连接(登录)权限,建立一个用户,就会自动授予其 usage 权限(默认授予)

删除用户

# 语法:

* DROP USER ‘用户名’@‘主机名’;

# 具体操作

* 删除 user2

46b67c0b5fa2c78f85d9a2e775eae11a.png

修改管理员密码

# 语法1:

* 管理员权限下 cmd 中输入 net stop mysql 关闭mysql服务

* 使用无验证方式启动 mysql服务:mysql --skip-grant-tables

* 打开新的cmd,输入 mysql,可以直接登录

* 修改密码

* 手动结束 mysqld.exe,并且启动 mysql 服务

# 语法2:

* mysqladmin -uroot -p password 新密码(前提是知道当前密码)

# 具体操作

* 将 root 管理员的新密码改为 123456

5d3469e15f37e8329b0f775f963eeb4e.png

修改普通用户密码

# 语法:

* SET PASSWORD FOR ‘用户名’@‘主机名’=password('新密码');

* 或者 UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名';

* 需要在 MySQL 登录的情况下操作

# 具体操作:

* 将 user1@localhost 用户的密码改成 666666

5e160fa2108c36ae17cc5d9d47ca440f.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值