目录
数据库设计简介
表关系(多对多)
表关系(一对多)
表关系之一对一
多表查询
笛卡尔积现象
内连接查询
外连接查询
嵌套查询(子查询)
事务操作
事务的概念
手动提交事务
自动提交事务
事务原理和四大特征
事务原理
事务的四大特征
事务的并发访问引发的三个问题(面试)
事务的隔离级别
首页 数据库 mysql教程 mysql设计概念及多表查询和事务操作

mysql设计概念及多表查询和事务操作

May 23, 2022 pm 06:37 PM
mysql

<p>本篇文章给大家带来了关于<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">视频教程</a>的相关知识,其中主要介绍了关于数据库设计概念的相关问题,包括了设计简介、多表查询、事务操作等等内容,下面一起来看一下吧,希望对大家有帮助。</p> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/628b6328be705537.jpg" class="lazy" alt="mysql设计概念及多表查询和事务操作" ></p> <p>推荐学习:<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">mysql视频教程</a></p> <h2 id="数据库设计简介">数据库设计简介</h2> <p><strong>1.数据库设计概念</strong></p> <ul> <li>数据库设计就是根据业务系统具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型。</li> <li>建立数据库中的<code>表结构</code>以及<code>表与表之间的关联关系</code>的过程。</li> <li>有哪些表?表里有哪些字段?表和表之间有什么关系?</li> </ul> <p><strong>2.数据库设计步骤</strong></p> <ul> <li><p>需求分析:数据库是什么?数据具体有哪些属性?数据与属性的特点是什么?</p></li> <li><p>逻辑分析:通过<code>ER图</code>对数据库进行逻辑建模,不需要考虑我们所选用的数据库管理系统。</p></li> <li><p>物理设计:根据数据库自身的特点把逻辑设计转换为物理设计。</p></li> <li><p>维护设计:对新的需求进行建表和对表的优化。</p></li> </ul> <p><strong>3.表关系简介</strong></p> <ul> <li><p>在真实的开发中,一个项目中的数据,一般都会保存在同一个数据库中,但是不同的数据需要保存在不同的数据表中。这时不能把所有的数据都保存在同一张表中。</p></li> <li><p>那么在设计保存数据的数据表时,我们就要根据具体的数据进行分析,然后把同一类数据保存在同一张表中,不同的数据进行分表处理。</p></li> <li><p>数据之间必然会有一定的联系,我们把不同的数据保存在不同的数据表中之后,同时还要在数据表中维护这些数据之间的关系。这时就会导致表和表之间必然会有一定的联系。这时要求设计表的人员,就需要考虑不同表之间的具体关系。</p></li> </ul> <p><mark>在数据库中,表总共存在三种关系,真实的数据表之间的关系:</mark><strong>多对多关系、一对多(多对一)</strong>、一对一(极少),(一对一关系就是我们之前学习的Map集合的key-value关系)</p> <h2 id="表关系-多对多">表关系(多对多)</h2> <p><strong>1.多对多</strong></p> <ul> <li>如:订单 和 商品</li> <li>一个商品对应多个订单,一个订单对应多个商品</li> <li>实现方式:建立第三张<code>中间表</code>,中间表至少包含<code>两个外键</code>,分别<code>关联两方主键</code><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/ad269369a7e12b5cbdb2c92327e55cb3-0.png" class="lazy" alt="在这里插入图片描述"><br><strong>说明:如果两张表是多对多的关系,需要创建第三张表,并在第三张表中增加两列,引入其他两张表的主键作为自己的外键。</strong> </li> </ul> <p><strong>2.外键约束</strong></p> <ul> <li>外键用来让两个表的数据之间建立链接,保证数据的一致性和完整性(例如上述多对多中的订单商品表来维护订单表和商品表之间的关系)</li> <li>使用之间表的目的是维护两表之间多对多的关系:<strong>中间表插入的数据,必须在多对多的主表中存在</strong>,<strong>如果主表的记录在中间表中维护了关系,就不能随意的删除。如果要删除,必须先要删除中间表关联的数据</strong> </li> </ul> <p><strong>3.外键约束语法</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 关键字解释:constraint: 添加约束,可以不写foreign key(当前表中的列名): 将某个字段作为外键references 被引用表名(被引用表的列名) : 外键引用主表的主键-- 创建表时添加外键约束CREATE TABLE 表名(    列名 数据类型,    …   [CONSTRAINT] [外键名称] FOREIGN KEY(外键列名) REFERENCES 主表(主表列名) ); -- 建完表后添加外键约束ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);-- 删除约束ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;</pre><div class="contentsignin">登录后复制</div></div> <p><strong>4.创建外键约束</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 订单表CREATE TABLE tb_orders(     id           int primary key auto_increment,     payment      double(10, 2),     payment_type TINYINT, -- 0 微信支付  1 支付宝支付     status       TINYINT  -- 0 未付款  1 已经支付);-- 商品表CREATE TABLE tb_goods(     id    int primary key auto_increment,     title varchar(100),     price double(10, 2));-- 订单商品中间表CREATE TABLE tb_order_goods(     id       int primary key auto_increment,     order_id int, -- 外键,来自于订单表的主键     goods_id int, -- 外键,来自于商品表的主键     count    int,  -- 购买商品数量     foreign key(order_id) references tb_orders(id),     foreign key(goods_id) references tb_goods(id));</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/ad269369a7e12b5cbdb2c92327e55cb3-1.png" class="lazy" alt="在这里插入图片描述"><br><strong>5.外键级联</strong></p> <p><mark>在修改和删除主表的主键时,同时更新或删除从表的外键值,称为级联操作</mark></p> <ul> <li> <code>ON UPDATE CASCADE</code> – 级联更新,主键发生更新时,外键也会更新</li> <li> <code>ON DELETE CASCADE</code> – 级联删除,主键发生删除时,外键也会删除</li> </ul> <p><strong>6.总结</strong></p> <blockquote> <p>1.为何要引用外键约束?</p> <ul><li>让表的数据有效性,正确性。提高查询效率。</li></ul> <p>2.添加外键约束语法?</p> <ul><li>constraint 外键约束名 foreign key(当前表的字段名) references 主表(主键)</li></ul> <p>3.有了外键约束操作数据注意事项?</p> <ul> <li>要求添加数据需要先添加主表,然后添加从表。</li> <li>要求删除数据需要先删除从表,然后再删除主表。</li> </ul> </blockquote> <h2 id="表关系-一对多">表关系(一对多)</h2> <p><strong>一对多(多对一)</strong></p> <ul> <li>如:部门表 和 员工表</li> <li>一个部门对应多个员工,一个员工对应一个部门</li> <li>实现方式:<mark>在多的一方建立外键,指向一的一方的主键</mark> </li> </ul> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/ad269369a7e12b5cbdb2c92327e55cb3-2.png" class="lazy" alt="在这里插入图片描述"></p> <h2 id="表关系之一对一">表关系之一对一</h2> <p><strong>一对一</strong></p> <ul> <li>如:用户和 用户信息</li> <li>一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能</li> <li>实现方式:在任意一方加入外键,关联另一方主键,并且设置外键为<strong>唯一</strong><code>(UNIQUE)</code> </li> </ul> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/efe2de8ea05d57aa111c2c60576fb57c-3.png" class="lazy" alt="在这里插入图片描述"></p> <h1 id="多表查询">多表查询</h1> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/efe2de8ea05d57aa111c2c60576fb57c-4.png" class="lazy" alt="在这里插入图片描述"><br><strong>准备数据</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 价格create table price(     id    int primary key auto_increment,     price double);-- 水果 create table fruit(     id       int primary key auto_increment,     name     varchar(20) not null,     price_id int,     foreign key (price_id) references price (id));-- 数据insert into pricevalues (1, 2.30);insert into pricevalues (2, 3.50);insert into pricevalues (4, null);insert into fruitvalues (1, '苹果', 1);insert into fruitvalues (2, '橘子', 2);insert into fruitvalues (3, '香蕉', null);</pre><div class="contentsignin">登录后复制</div></div> <h2 id="笛卡尔积现象">笛卡尔积现象</h2> <p><strong>1.什么是笛卡尔积现象</strong></p> <ul> <li>笛卡尔积问题:把多张表放在一起,同时去查询,会得到一个结果,而这结果并不是我们想要的数据,这个结果称为笛卡尔积。</li> <li>笛卡尔积缺点:查询到的结果冗余了,里面有很多错误的数据,需要过滤。</li> <li>多表查询语法:<code>select * from 表名1,表名2;</code> </li> </ul> <p><em>需求:查询两张表中关于水果的信息,要显示水果名称和水果价格</em></p> <p><strong>表设计原则:将价格的主键作为水果的外键</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 多表查询语法(同时查询多个表获取到需要的数据)select * from 表名1,表名2;-- 查询价格(我们向查询水果对应的价格,需要将水果表和价格表同时进行查询;)select * from fruit,price;</pre><div class="contentsignin">登录后复制</div></div> <p>查询结果:<br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/efe2de8ea05d57aa111c2c60576fb57c-5.png" class="lazy" alt="在这里插入图片描述"><br><strong>2.笛卡尔积产生原因</strong><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/efe2de8ea05d57aa111c2c60576fb57c-6.png" class="lazy" alt="在这里插入图片描述"><br><code>fruit</code>表中的每一条记录,都和<code>price</code>表中的每一条进行匹配连接。所得到的最终结果是:fruit表中的条目数乘以<code>price</code>表中的数据的条目数。</p> <p><mark>将<code>fruit</code>表的每行记录和<code>price</code>表的每行记录组合的结果就是笛卡尔积</mark></p> <p><strong>3.如何避免笛卡尔积</strong></p> <p><mark>解决上述查询的方案:在查询两张表的同时添加条件进行过滤,比如fruit表的id和必须和price表的id相同</mark></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 条件过滤笛卡尔积select * from fruit,price where fruit.price_id=price.id;</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/3b857041b4c528113c17679e4015a6b9-7.png" class="lazy" alt="在这里插入图片描述"></p> <h2 id="内连接查询">内连接查询</h2> <p><strong>1.什么是内连接</strong></p> <blockquote><p>内连接查询又称为交集查询,也就是查询只显示满足条件的数据</p></blockquote> <p><strong>2.显示内连接</strong></p> <p>显示内连接:使用<code>INNER JOIN...ON</code>语句,可以省略<code>INNER</code>关键字</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 语法核心select * from 表名1 inner join 表名2 on 条件;-- 或者select * from 表名1 join 表名2 on 条件;</pre><div class="contentsignin">登录后复制</div></div> <p><strong>3.隐式内连接</strong></p> <p>看不到<code>JOIN</code>关键字,条件使用<code>WHERE</code>指定</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">select 列名,列名,... from 表名1,表名2 where 表名1.列名=表名2.列名;</pre><div class="contentsignin">登录后复制</div></div> <p><strong>4.示例</strong></p> <p><em>查询水果的价格</em></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 隐式内连接select * from fruit,price where fruit.price_id=price.id;-- 显式内连接select * from fruit inner join price on fruit.price_id=price.id;</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/3b857041b4c528113c17679e4015a6b9-8.png" class="lazy" alt="在这里插入图片描述"><br><em>查询苹果的信息,显示苹果的id,名字,价格</em></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 方式1select fruit.id, fruit.name, price.pricefrom fruit,      pricewhere fruit.price_id = price.id  and fruit.name = '苹果';-- 方式2select fruit.id, fruit.name, price.pricefrom fruit         inner join      price     on fruit.price_id = price.id         and fruit.name = '苹果';</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/3b857041b4c528113c17679e4015a6b9-9.png" class="lazy" alt="在这里插入图片描述"><br><strong>5.总结</strong></p> <p>1.内连接作用?</p> <ul> <li><p>过滤笛卡尔积</p></li> <li><p>获取两表的交集部分(都满足条件的部分)</p></li> </ul> <p>2.什么是隐式内连接和显示内连接?</p> <ul> <li>隐式内连接:看不到JOIN:<code>select 列名,列名....from 表名1,表名2 where 表名1.列名=表名2.列名;</code> </li> <li>显示内连接:看得到JOIN:<code>select * from 表名1 inner join 表名2 on 条件;</code> </li> </ul> <p>3.内连接查询步骤?</p> <ul> <li>1)确定查询几张表</li> <li>2)确定表连接条件</li> <li>3)根据需要在操作</li> </ul> <h2 id="外连接查询">外连接查询</h2> <p><strong>1.左外连接</strong></p> <ul> <li>左表的记录全部显示出来</li> <li>外表只会显示符合搜索条件的记录</li> </ul> <p>语法格式:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">select * from 表1 left [outer] join 表2 on 条件;</pre><div class="contentsignin">登录后复制</div></div> <p>说明:</p> <ul> <li> <code>left</code>关键字左边的表定义为<mark>左表</mark>,<code>left</code>关键字右边的表定义为<mark>右表</mark>,查询的内容以<mark>左表为主</mark> </li> <li>如果左表有数据,而右表没有数据对应的数据,仍然会把左表数据进行显示</li> <li> <code>outer</code>关键字可以省略</li> </ul> <p>练习:</p> <p><em>不管能否查到水果对应价格,都要把水果显示出来</em></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 左外连接查询select * from fruit left outer join price on fruit.price_id=price.id;</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/3b857041b4c528113c17679e4015a6b9-10.png" class="lazy" alt="在这里插入图片描述"><br><strong>2.右外连接</strong></p> <ul> <li>右表的记录全部表示出来</li> <li>左表只会显示符合搜索条件的记录</li> </ul> <p>语法格式:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">select * from 表名1 right [outer] join 表名2 on 条件;</pre><div class="contentsignin">登录后复制</div></div> <p>说明:</p> <ul> <li> <code>right</code>关键字左边的表定义为左表,<code>right</code>关键字右边的表定义为右表,查询的内容以<mark>右表为主</mark> </li> <li>如果右表没有数据,而左表没有对应的数据,仍然会把右表数据进行显示</li> <li> <code>outer</code>关键字可以省略</li> </ul> <p>练习:</p> <p><em>不管能否查到价格对应的水果,都要把价格显示出来</em></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">select * from fruit right outer join price on fruit.price_id=price.id;</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/bf39a634faa46618bcd456e099b97614-11.png" class="lazy" alt="在这里插入图片描述"><br> 总结:</p> <p>1.掌握左外连接查询格式?</p> <ul> <li><code>select * from 表1 left outer join 表2 on 条件;</code></li> <li>表1看作为左表,表2看做为右表</li> </ul> <p>2.左外连接查询特点?</p> <ul><li>在满足要求的基础上保证左表的数据全部显示</li></ul> <p>3.掌握右外连接查询格式?</p> <ul><li><code>select * from 表1 right outer join 表2 on 条件;</code></li></ul> <p>4.右外连接查询特点?</p> <ul><li>在满足要求的基础上,保证右表的数据全部显示</li></ul> <h2 id="嵌套查询-子查询">嵌套查询(子查询)</h2> <p><strong>1.什么是子查询</strong></p> <p><mark><strong>一条查询语句结果作为另一条查询语法一部分。</strong></mark></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">SELECT 查询字段 FROM 表 WHERE 条件;举例:SELECT * FROM employee WHERE salary=(SELECT MAX(salary) FROM employee);</pre><div class="contentsignin">登录后复制</div></div> <p>说明:子查询需要放在()中</p> <p>三种子查询情况:<code>单行单列</code>、<code>多行单列</code>、<code>多行多列</code>。</p> <p><strong>2.单行单列</strong></p> <p>子查询结果是<code>单列</code>,在<code>WHERE</code>后面作为<code>条件</code></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">SELECT 查询字段 FROM 表 WHERE 字段=(子查询);</pre><div class="contentsignin">登录后复制</div></div> <p>通常使用比较运算符: <code>></code> 、<code>>=</code> 、<code><</code>、<code><=</code>、<code>=</code>等</p><p><strong>3.多行单列</strong></p><p>子查询结果是多行单列,结果集类似于一个数组,在<code>WHERE</code>后面作为<code>条件</code>,父查询使用<code>IN</code>运算符</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- IN表示在数值中SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);</pre><div class="contentsignin">登录后复制</div></div><p><strong>4.多行多列</strong></p><p>子查询结果是<code>多列</code>,在<code>FROM</code>后面作为<code>表</code></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;</pre><div class="contentsignin">登录后复制</div></div><p><mark>注意:子查询作为表需要取别名,使用as,可以省略,否则这张表没用名称无法访问表中的字段</mark></p><h2 id="事务操作">事务操作</h2><h2 id="事务的概念">事务的概念</h2><p><strong>什么是事务</strong></p><p>在实际的业务开发中,有些业务操作要多次访问数据库。一个业务要发送多条SQL语句给数据库执行。需要将多次访问数据库的操作视为一个整体来执行,要么所有的SQL语句全部执行成功。如果其中有一条SQL语句失败,就进行事务的回滚,所有的SQL语句全部执行失败。</p><p>简而言之,事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败。</p><p>事务作用:<mark>保证在一个事务中多次操作数据库表中数据时,要么全都成功,要么全都失败。</mark></p><p><strong>事务的应用场景声明</strong></p><p>关于事务在实际中的应用场景:</p><p>假设我在淘宝买了一部手机,然后当我付完款,钱已经从我的账户中扣除。正当此时,淘宝转账系统宕机了,那么此时淘宝还没有收到钱,而我的账户的钱已经减少了,这样就会导致我作为买家钱已经付过,而卖家还没有收到钱,他们不会发货物给我。这样做显然是不合理。实际生活中是如果淘宝出问题,作为用户的账户中钱是不应该减少的。这样用户就不会损失钱。</p><p>还有种情况,就是当我付完款之后,卖家看到我付款成功,然后直接发货了,我如果有权限操作,我可以撤销,这样就会导致我的钱没有减少,但是卖家已经发货,同样这种问题在实际生活中也是不允许出现的。</p><p><strong>MySQL中可以有两种方式进行事务的操作:</strong></p><ul><li>手动提交事物:先开启,在提交</li><li>自动提交事物(默认的):即执行一条<code>sql</code>语句提交一次事物</li></ul><p><strong>数据准备</strong></p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"># 创建账号表create table account( id int primary key auto_increment, name varchar(20), money double);# 初始化数据insert into account values (null,&#39;a&#39;,1000);insert into account values (null,&#39;b&#39;,1000);</pre><div class="contentsignin">登录后复制</div></div><h2 id="手动提交事务">手动提交事务</h2><p><strong>手动提交事务有关的sql语句</strong></p><table><thead><tr class="firstRow"><th align="center">SQL语句</th><th>描述</th></tr></thead><tbody><tr><td align="center"><code>start transaction</code></td><td>开启手动控制事物</td></tr><tr><td align="center"><code>commit</code></td><td>提交事物</td></tr><tr><td align="center"><code>rollback</code></td><td>回滚事物</td></tr></tbody></table><p><strong>手动提交事务使用步骤</strong></p><ul><li>开启事务–>执行SQL语句–>成功–>提交事务<li>开启事务–>执行SQL语句–>失败–>回滚事务</li> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/bf39a634faa46618bcd456e099b97614-12.png" class="lazy" alt="在这里插入图片描述"><br><strong>演示案例</strong>:演示提交事务,a给b转账100元</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 1.开启事务start transaction;-- 2.执行sql语句update account set money=money-100 where name='a';update account set money=money+100 where name='b';-- 3.提交事务commit;</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/bf39a634faa46618bcd456e099b97614-13.png" class="lazy" alt="在这里插入图片描述"><br><strong>案例演示</strong>:演示回滚事务,a给b转账100元</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 1.开启事务start transaction;-- 2.执行sql语句update account set money=money-100 where name='a';update account set money=money+100 where name='b';-- 3.回滚事务rollback;</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/bf39a634faa46618bcd456e099b97614-14.png" class="lazy" alt="在这里插入图片描述"><br><strong>注意:</strong></p> <ul> <li>提交事务(<code>commit</code>) :事务提交之后,<code>sql</code>语句对数据库产生的操作才会被永久的保存</li> <li>事务的回滚(<code>rollback</code>):撤销已经成功执行的<code>sql</code>语句,回到开启事务之前的状态</li> <li>只要提交事务,那么数据就会长久保存了,就不能回滚事务了。即提交或者回滚事务都是代表结束当前事务的操作</li> </ul> <h2 id="自动提交事务">自动提交事务</h2> <p>MySQL的每一条DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,执行完毕自动提交事务,MySQL默认开始自动提交事务。自动提交,通过修改mysql全局变量<code>autocommit</code>进行控制。</p> <p><strong>通过以下命令可以查看当前autocommit模式</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">show variables like '%commit%';</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/d50eb658dc14e9bf60da47ceeaf721ba-15.png" class="lazy" alt="在这里插入图片描述"><br><strong>设置自动提交的参数为OFF</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">set autocommit = 0;  -- 0:OFF  1:ON</pre><div class="contentsignin">登录后复制</div></div> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/d50eb658dc14e9bf60da47ceeaf721ba-16.png" class="lazy" alt="在这里插入图片描述"><br><strong>案例演示</strong></p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">-- 自动提交事务:每条sql语句就是一个事务,那么执行一条sql语句就会提交一次事务-- mysql数据库就是自动提交事务-- a给b转账100元update account set money=money-100 where name='a';update account set money=money+100 where name='b';-- 查看mysql是否自动提交事务-- autocommit的值是on表示自动提交事务,值是off表示关闭自动提交事务show variables like '%commit%';-- 我们可以使用命令临时设置mysql变为手动提交事务,即将自动提交事务关闭-- 下次重新连接mysql依然是自动提交事务set autocommit = 0; -- 0 表示关闭自动提交事务 1表示开启自动事务update account set money=money-100 where name='a'</pre><div class="contentsignin">登录后复制</div></div> <p><strong>注意:</strong></p> <p>1)MySql默认自动提交。即执行一条sql语句提交一次事务。</p> <p>2)设置autocommit为<code>off</code>状态,只是临时性的,下次重新连接mysql,autocommit依然变为<code>on</code>状态。</p> <p>3)如果设置autocommit为<code>off</code>状态,那么当我们执行一条sql语句,就不会自动提交事务,重新启动可视化工具,数据并没有改变。</p> <p>4)如果设置autocommit为<code>on</code>状态,如果我们先执行<code>start transaction</code> 然后在执行修改数据库的语句:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">update account set money = money-100 where name='a'; update account set money = money+100 where name='b';</pre><div class="contentsignin">登录后复制</div></div> <p>那么此时就表示上述修改数据库的sql语句都在同一个事务中,此时必须手动提交事务,即<code>commit</code>;</p> <p>换句话说,如果我们手动开启事务<code>start transaction</code>那么此时mysql就不会自动提交事务,必须手动提交事务。</p> <p>5)如果设置autocommit为on状态,如果我们不执行<code>start transaction</code> 直接执行修改数据库的语句:</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">update account set money = money-100 where name='a';update account set money = money+100 where name='b';</pre><div class="contentsignin">登录后复制</div></div> <p>那么此时mysql就会自动提交事务,即上述每条sql语句就是一个事务</p> <h2 id="事务原理和四大特征">事务原理和四大特征</h2> <h2 id="事务原理">事务原理</h2> <p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/d50eb658dc14e9bf60da47ceeaf721ba-17.png" class="lazy" alt="在这里插入图片描述"><br><strong>原理说明</strong></p> <ol> <li>一个用户登录成功以后,服务器会创建一个临时日志文件。日志文件用来保存用户事务状态。</li> <li>如果没有使用事务,则所有的操作直接写到数据库中,不会使用日志文件。</li> <li>如果开启事务,将所有的写操作写到日志文件中。</li> <li>如果这时用户提交了事务,则将日志文件中所有的操作写到数据库中。</li> <li>如果用户回滚事务,则日志文件会被清空,不会影响到数据库的操作。</li> </ol> <h2 id="事务的四大特征">事务的四大特征</h2> <p><strong>事务的四大特征(ACID)</strong></p> <p>数据库的事务必须具备<strong>ACID</strong>特征,<strong>ACID</strong>是指<code>Atomicity</code>(原子性)、<code>Consistensy</code>(一致性)、<code>Isolation</code>(隔离性)和<code>Durabiliyt</code>(持久性)</p> <p><strong>隔离性(Isolation)</strong></p> <p>多个用户并发的访问数据库时,一个用户的事务不能被其他用户的事物干扰,多个并发的事务之间相互隔离<br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/1752463693924621c150302b0ef05d33-18.png" class="lazy" alt="在这里插入图片描述"><br><strong>持久性(Durability)</strong></p> <p>指一个事务一旦被提交,它对数据库的改变是永久性的,哪怕数据库发生异常,重启之后数据依然会存在<br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/1752463693924621c150302b0ef05d33-19.png" class="lazy" alt="在这里插入图片描述"><br><strong>原子性(Atomicity)</strong></p> <p>指事务包装的一组sql语句(一组业务逻辑)是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生</p> <p><strong>一致性(Consistency)</strong></p> <p>一致性是指数据处于一种语义上有意义且正确的状态;</p> <p>事务一致性是指事务执行的结果必须是使数据从一个一致性状态变到另一个一致性状态。</p> <p>事务的成功与失败,最终数据库的数据都是符合实际生活的<strong>业务逻辑</strong>。一致性绝大多数<strong>依赖业务逻辑</strong>和原子性<br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/1752463693924621c150302b0ef05d33-20.png" class="lazy" alt="在这里插入图片描述"></p> <h2 id="事务的并发访问引发的三个问题-面试">事务的并发访问引发的三个问题(面试)</h2> <p>事务在操作时的理想状态:多个事务之间互不影响,如果隔离级别设置不当就可能引发并发访问问题</p> <table> <thead><tr class="firstRow"> <th align="center">并发访问的问题</th> <th align="left">含义</th> </tr></thead> <tbody> <tr> <td align="center">脏读</td> <td align="left">一个事务读取到了另一个事务中尚<strong>未提交的数据</strong>。最严重,杜绝发生。</td> </tr> <tr> <td align="center">不可重复读</td> <td align="left">一个事务中两次读取的<strong>数据内容</strong>不一致,要求的是一个事务中多次读取时数据是不一致的,这是事务<strong>update时</strong>引发的问题</td> </tr> <tr> <td align="center">幻读(虚读)</td> <td align="left">一个事务内读取到了别的<strong>事务插入或者删除的数据</strong>,导致前后读取记录行数不同。这是<strong>insert或delete</strong>时引发的问题</td> </tr> </tbody> </table> <p><strong>1.脏读:指一个事务读取了另外一个事务未提交的数据。(非常危险)</strong><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/1752463693924621c150302b0ef05d33-21.png" class="lazy" alt="在这里插入图片描述"><br><strong>2.不可重复读:在一个事务内多次读取表中的数据,多次读取的结果不同。</strong><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/78eb789e1e140a75b7f32d4c6cf9bac7-22.png" class="lazy" alt="在这里插入图片描述"><br><strong>3.幻读(虚读):一个事务内读取到了别的事务插入或者删除的数据,导致前后读取记录行数不同</strong><br><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/067/78eb789e1e140a75b7f32d4c6cf9bac7-23.png" class="lazy" alt="在这里插入图片描述"><br><strong>4.总结</strong></p> <ul> <li><p>赃读:一个事务读取另一个事务还没有提交的数据,一定避免。<br> 不可重复读:一个事务读取多次数据内容不一样,主要是update语句。事务已经提交了。 可以发生的。</p></li> <li><p>幻读(虚读):一个事务读取多次数量不一样,主要是delete或者insert语句。事务已经提交了。可以发生的。</p></li> </ul> <h2 id="事务的隔离级别">事务的隔离级别</h2> <p>通过以上问题演示,我们发现如果不考虑事务的隔离性,会遇到脏读、不可重复读和虚读等问题。所以在数据库中我们要对上述三种问题进行解决。MySQL数据库规范规定了4种隔离级别,分别用于描述两个事务并发的所有情况。</p> <p><strong>事物隔离级别</strong></p> <p>上面的级别最低,下面的级别最高。<code>是</code>表示会出现这种问题,<code>否</code>表示不会出现这种问题。</p> <table> <thead><tr class="firstRow"> <th>级别</th> <th>名字</th> <th>隔离级别</th> <th>脏读</th> <th>不可重复读</th> <th>幻读</th> <th>数据库默认隔离级别</th> </tr></thead> <tbody> <tr> <td>1</td> <td>读未提交</td> <td>read uncommitted</td> <td>是</td> <td>是</td> <td>是</td> <td><br></td> </tr> <tr> <td>2</td> <td>读已提交</td> <td>read committed</td> <td>否</td> <td>是</td> <td>是</td> <td>Oracle和SQL Server</td> </tr> <tr> <td>3</td> <td>可重复读</td> <td>repeatable read</td> <td>否</td> <td>否</td> <td>是</td> <td>MySQL</td> </tr> <tr> <td>4</td> <td>串行化</td> <td>serializable</td> <td>否</td> <td>否</td> <td>否</td> <td><br></td> </tr> </tbody> </table> <p><strong>安全和性能对比</strong></p> <ul> <li><p>安全: 串行化>可重复读>读已提交>读未提交</p></li> <li><p>性能: 串行化<可重复读<读已提交<读未提交</p></li> </ul> <blockquote> <p>其实三个问题中,<strong>最严重的就是脏读</strong>(读取了错误数据),这个问题一定要避免;</p> <p>关于不可重复读和虚读其实并不是<strong>逻辑上的错误</strong>,而是数据的<strong>时效性</strong>问题,所以这种问题并不属于很严重的错误;</p> <p>如果对于数据的时效性要求不是很高的情况下,我们是可以接受不可重复读和虚读的情况发生的</p> </blockquote> <p>推荐学习:<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">mysql视频教程</a></p></code></p>

以上是mysql设计概念及多表查询和事务操作的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1668
14
CakePHP 教程
1428
52
Laravel 教程
1329
25
PHP教程
1273
29
C# 教程
1256
24
laravel入门实例 laravel入门实例 Apr 18, 2025 pm 12:45 PM

Laravel 是一款 PHP 框架,用于轻松构建 Web 应用程序。它提供一系列强大的功能,包括:安装: 使用 Composer 全局安装 Laravel CLI,并在项目目录中创建应用程序。路由: 在 routes/web.php 中定义 URL 和处理函数之间的关系。视图: 在 resources/views 中创建视图以呈现应用程序的界面。数据库集成: 提供与 MySQL 等数据库的开箱即用集成,并使用迁移来创建和修改表。模型和控制器: 模型表示数据库实体,控制器处理 HTTP 请求。

MySQL和PhpMyAdmin:核心功能和功能 MySQL和PhpMyAdmin:核心功能和功能 Apr 22, 2025 am 12:12 AM

MySQL和phpMyAdmin是强大的数据库管理工具。1)MySQL用于创建数据库和表、执行DML和SQL查询。2)phpMyAdmin提供直观界面进行数据库管理、表结构管理、数据操作和用户权限管理。

MySQL与其他编程语言:一种比较 MySQL与其他编程语言:一种比较 Apr 19, 2025 am 12:22 AM

MySQL与其他编程语言相比,主要用于存储和管理数据,而其他语言如Python、Java、C 则用于逻辑处理和应用开发。 MySQL以其高性能、可扩展性和跨平台支持着称,适合数据管理需求,而其他语言在各自领域如数据分析、企业应用和系统编程中各有优势。

解决数据库连接问题:使用minii/db库的实际案例 解决数据库连接问题:使用minii/db库的实际案例 Apr 18, 2025 am 07:09 AM

在开发一个小型应用时,我遇到了一个棘手的问题:需要快速集成一个轻量级的数据库操作库。尝试了多个库后,我发现它们要么功能过多,要么兼容性不佳。最终,我找到了minii/db,这是一个基于Yii2的简化版本,完美地解决了我的问题。

laravel框架安装方法 laravel框架安装方法 Apr 18, 2025 pm 12:54 PM

文章摘要:本文提供了详细分步说明,指导读者如何轻松安装 Laravel 框架。Laravel 是一个功能强大的 PHP 框架,它 упростил 和加快了 web 应用程序的开发过程。本教程涵盖了从系统要求到配置数据库和设置路由等各个方面的安装过程。通过遵循这些步骤,读者可以快速高效地为他们的 Laravel 项目打下坚实的基础。

解决MySQL模式问题:TheliaMySQLModesChecker模块的使用体验 解决MySQL模式问题:TheliaMySQLModesChecker模块的使用体验 Apr 18, 2025 am 08:42 AM

在使用Thelia开发电商网站时,我遇到了一个棘手的问题:MySQL模式设置不当,导致某些功能无法正常运行。经过一番探索,我找到了一个名为TheliaMySQLModesChecker的模块,它能够自动修复Thelia所需的MySQL模式,彻底解决了我的困扰。

在MySQL中解释外键的目的。 在MySQL中解释外键的目的。 Apr 25, 2025 am 12:17 AM

在MySQL中,外键的作用是建立表与表之间的关系,确保数据的一致性和完整性。外键通过引用完整性检查和级联操作维护数据的有效性,使用时需注意性能优化和避免常见错误。

比较和对比Mysql和Mariadb。 比较和对比Mysql和Mariadb。 Apr 26, 2025 am 12:08 AM

MySQL和MariaDB的主要区别在于性能、功能和许可证:1.MySQL由Oracle开发,MariaDB是其分支。2.MariaDB在高负载环境中性能可能更好。3.MariaDB提供了更多的存储引擎和功能。4.MySQL采用双重许可证,MariaDB完全开源。选择时应考虑现有基础设施、性能需求、功能需求和许可证成本。

See all articles