Mysql串讲


Mysql串讲

知识总结

【索引相关】

  • 索引的本质,什么情况下添加索引呢
  • 索引实现的数据结构:哈希表,有序数组,搜索树(即使B树)
  • mysql中索引的实现,为什么最后是B+树呢,带有顺序访问指针的B+Tree
  • mysql中myisam和Innodb的区别,mysql的存储引擎有那些呢
  • 联合索引,即索引的最左前缀原则
  • 覆盖索引,即如何避免回表,例如select count(*) from T
  • 索引下推,可以在索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表字数

【数据库事务与锁】

  • 数据库事务的4个特性,ACID,原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)
  • 脏读、不可重复读、幻读
  • mysql的4种隔离级别
  • MVCC(多版本并发控制):在MySQL中,InnoDB为数据库中的每一行添加了三个隐藏字段:DB_TRX_ID(事务版本号)、DB_ROLL_PTR(回滚指针)、DB_ROW_ID(隐藏ID,一般是主键ID)
  • 行级锁,表级锁,页面锁(BDB存储引擎使用的是这个,知道概念就可以了的(5.1之后就不直接支持了,因为BDB被oracle收购了))
  • 在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read),哪些是快照读,哪些是当前读
    select * from table where ? lock in share mode;读取记录加S锁 (共享锁),实际中很少采用,其它的当前读加排他锁(X锁)
  • 间隙锁(rr级别下)
  • 意向锁(Intention Locks)【补充了解】:
    需要强调一下,意向锁是一种不与行级锁冲突表级锁,这一点非常重要。意向锁是有数据引擎自己维护的,用户无法手动操作意向锁意向锁分为两种:
    意向共享锁(intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁)— 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
    SELECT column FROM table ... LOCK IN SHARE MODE;
    意向排他锁(intention exclusive lock, IX):事务有意向对表中的某些行加排他锁(X锁)— 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
    SELECT column FROM table ... FOR UPDATE;
    意向锁的存在意义:
    意向锁是表级的,意向锁之间是互相兼容的。
    意向锁不会与行级的共享 / 排他锁互斥!!!,IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。
    目的就是第1个事务加了意向锁以后,第2个事务如果是表级锁的话就不用去检查行级锁了
  • gap锁,即间隙锁;next-lock key,即行锁+间隙锁

【实际应用】

  • sql语法,增删查改,添加/修改字段、添加/修改索引,删除表
  • mysql的执行计划,如何判断索引是否生效
  • select—from—where—groupby—having—orderby
  • 各类join,复杂sql如何编写,主要的常见函数
  • 面试中的复杂sql如何编写,详细见范例,要求范例里面的都会写
  • 实际的数据库的建表原则

数据库

什么是数据库事务?数据库事务的四个特性是什么?

解析:事务是很重要的概念,不管在数据库里还是问到项目框架,都会被问到。简单来说——

事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。

157535281975806

四个特性:

  • 原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;

  • 一致性(Consistency):执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;

  • 隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

  • 持久性(Durability): 一个事务被提交之后,它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

  • 事务的并发问题有哪些?数据库的隔离级别有哪几种?是不是隔离级别越高越好?我们应该如何选择隔离级别?

    并发问题:

    • 脏读
    • 丢失修改
    • 不可重复读
    • 幻读

    隔离级别:

    • READ-UNCOMMITTED(读取未提交)
    • READ-COMMITTED(读取已提交)
    • REPEATABLE-READ(可重复读)
    • SERIALIZABLE(可串行化)

    隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读等并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

请分别举例说明幻读和不可重复读,并描述一下它们之间的区别

不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。

Mysql的默认隔离级别是什么?那么Mysql在实际企业中一般使用的隔离级别是什么吗?为什么?

Mysql默认隔离级别是可重复读。

第二问参考:互联网项目中选择Mysql的哪种隔离级别

为什么要使用索引?

  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  • 可以大大加快数据的检索速度(大大减少检索的数据量),这是创建索引的最主要原因
  • 帮助服务器避免排序和临时表
  • 可以将随机IO变为顺序IO

索引这么多优点,为什么不对表中每个字段都创建索引呢?

  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态维护,这样就降低了数据的维护速度
  • 索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

索引是如何提升查询速度的?

将无序的数据变成相对有序的数据(就像目录一样)。

请说出你知道的索引失效的几种情况?

  1. 有or必全有索引;

  2. 复合索引未用左列字段;

  3. like以%开头;

  4. 需要类型转换;

  5. where中索引列有运算;

  6. where中索引列使用了函数;

  7. 如果mysql觉得全表扫描更快时(数据少);

    详细解释查看索引失效的几种情况

什么是聚簇索引与非聚簇索引

  • 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据

  • 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,

    澄清一个概念:innodb中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值。

    详细了解请参照聚簇索引和非聚簇索引

Mysql索引主要使用的数据结构有哪些?

  • 哈希索引:对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引;
  • 有序数组:有序数组在等值查询和范围查询场景中的性能都非常优秀。用二分法就可以快速找到(时间复杂度为O(logN))。但是如果要往中间插入一条数据,则必须挪动后面的所有记录,成本较高。因此,有序数组只适用于静态存储引擎,即数据表一旦建立后不再会修改。
  • BTree索引:Mysql的BTree索引使用的是B树的B+Tree。但对于主要的两种存储引擎(MyISAM和InnoDB)的实现方式是不同的。

谈谈MyISAM和innoDb实现Btree索引方式的区别

  • MyISAM:B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址读取相应的数据记录,这被称为“非聚簇索引”
  • InnoDB:其数据文件本身就是索引文件。相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按照B+Tree组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引,这被称为“聚簇索引(或聚集索引)”,而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是与MyISAM不同的地方。在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再走一遍主索引。因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

B+tree与B-tree的区别是什么?为什么B+tree更适合做文件索引?

  • B+tree与B-tree的区别:

    在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

  • B+tree更适合做文件索引,因为B+ Tree的内部节点并没有指向关键字具体信息的指针,所以他的内部节点比其他结构的更小,同样大小的盘块能够容纳更多的单位索引结构,一次性读入内存的关键字信息索引就更多,相对来说IO读写次数也就少很多。

什么是覆盖索引?请举例说明

如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称之为“覆盖索引”。我们知道在InnoDB存储引擎中,如果不是主键索引,叶子节点存储的是主键和列值。最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢。而覆盖索引就是把要查询出的列和索引是对应的,不做回表操作。

举例:创建一个索引(username,age)

在查询数据的时候执行sql

  select username,age from user where username='Java' and age = 22;

要查询出的列和索引是对应的,不要做回表操作。

谈谈你对最左前缀原则的理解?

MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如user表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:

  select * from user where name=xx and city=xx ; //可以命中索引
  select * from user where name=xx ; // 可以命中索引
  select * from user where city=xx ; // 无法命中索引

这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,如 city= xx and name =xx,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。

由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。ORDER BY子句也遵循此规则。

mysql中innoDb和MyISAM有什么区别呢

MyISAM是MySQL的默认数据库引擎(5.5版之前)。虽然性能极佳,而且提供了大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复。不过,5.5版本之后,MySQL引入了InnoDB(事务性数据库引擎),MySQL 5.5版本后默认的存储引擎为InnoDB。

大多数时候我们使用的都是 InnoDB 存储引擎,但是在某些情况下使用 MyISAM 也是合适的比如读密集的情况下。(如果你不介意 MyISAM 崩溃恢复问题的话)。

两者的对比:

  1. 是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
  2. 是否支持事务和崩溃后的安全恢复: MyISAM 强调的是性能,每次查询具有原子性,其执行速度比InnoDB类型更快,但是不提供事务支持。但是InnoDB 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
  3. 是否支持外键: MyISAM不支持,而InnoDB支持。
  4. 是否支持MVCC :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTEDREPEATABLE READ 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。

谈谈如何对SQL进行优化?

例如:应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。
互联网项目中,尽量避免使用存储过程和触发器(已经被pass,都是用代码来整合),尽量避免多表关联查询.
where条件里面的必须有1个带索引,不要使用not in或者exists语句,这种情况下会全表扫描,索引不生效,需要优化
尽量不要使用存储过程和触发器,因为这个依赖于数据库去实现,在高并发情况下可能导致数据库瘫痪

如何用explain分析sql执行效率

explain用来分析sql查询语句的执行效率,desc命令同样的效果。

语法:explain 查询语句

举个栗子:explain select * from news;

输出:

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

下面对各个属性进行了解:

1、id:这是SELECT的查询序列号

2、select_type:select_type就是select的类型,可以有以下几种:

SIMPLE:简单SELECT(不使用UNION或子查询等)

PRIMARY:最外面的SELECT

UNION:UNION中的第二个或后面的SELECT语句

DEPENDENT UNION:UNION中的第二个或后面的SELECT语句,取决于外面的查询

UNION RESULT:UNION的结果。

SUBQUERY:子查询中的第一个SELECT

DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询

DERIVED:导出表的SELECT(FROM子句的子查询)

3、table:显示这一行的数据是关于哪张表的

4、type:这列最重要,显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。

结果值从好到坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。

5、possible_keys:列指出MySQL能使用哪个索引在该表中找到行

6、key:显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL

7、key_len:显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好

8、ref:显示使用哪个列或常数与key一起从表中选择行。

9、rows:显示MySQL认为它执行查询时必须检查的行数。

10、Extra:包含MySQL解决查询的详细信息,也是关键参考项之一。

Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

Not exists
MYSQL 优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,

就不再搜索了

Range checked for each

Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

Using filesort
看 到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来 排序全部行

Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表 的全部的请求列都是同一个索引的部分的时候

Using temporary
看到这个的时候,查询需要优化了。这 里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index, 这就会发生,或者是查询有问题

其他一些Tip:当type 显示为 “index” 时,并且Extra显示为“Using Index”, 表明使用了覆盖索引。

请举出可能形成数据库死锁的原因?如何能避免死锁?

目前,我们已经探讨了许多关于数据库锁的问题,锁能够有效地解决并发的问题,但这也带来了一个严重的缺点,那就是死锁。

死锁在操作系统中指的是两个或两个以上的进程在执行的过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或者系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

在操作系统中,死锁的处理是一个重要的话题,也已经有较为成熟的解决方法,如银行家算法等,在这边我们就不再阐述,只讨论数据库中的死锁。

数据库中常见的死锁原因与解决方案有:

  1. 事务之间对资源访问顺序的交替

出现原因:
一个用户A 访问表A(锁住了表A),然后又访问表B;另一个用户B 访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁就产生了。

解决方法:
这种死锁比较常见,是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理, 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源

  1. 并发修改同一记录

出现原因:主要是由于没有一次性申请够权限的锁导致的。参考:记录一次死锁排查过程

用户A查询一条纪录,然后修改该条纪录;这时用户B修改该条纪录,这时用户A的事务里锁的性质由查询的共享锁企图上升到独占锁,而用户B里的独占锁由于A有共享锁存在所以必须等A释放掉共享锁,而A由于B的独占锁而无法上升的独占锁也就不可能释放共享锁,于是出现了死锁。这种死锁比较隐蔽,但在稍大点的项目中经常发生。

解决方法:

  • 乐观锁,实现写-写并发
  • 悲观锁:使用悲观锁进行控制。悲观锁大多数情况下依靠数据库的锁机制实现,如Oracle的Select … for update语句,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。
  1. 索引不当导致的死锁

出现原因:
如果在事务中执行了一条不满足条件的语句,执行全表扫描,把行级锁上升为表级锁,多个这样的事务执行后,就很容易产生死锁和阻塞。类似的情况还有当表中的数据量非常庞大而索引建的过少或不合适的时候,使得经常发生全表扫描,最终应用系统会越来越慢,最终发生阻塞或死锁。

另外一种情况是由于二级索引的存在,上锁的顺序不同导致的,这部分在讨论索引时会提到。参考:https://www.cnblogs.com/LBSer/p/5183300.html

解决方法:

SQL语句中不要使用太复杂的关联多表的查询;使用“执行计划”对SQL语句进行分析,对于有全表扫描的SQL语句,建立相应的索引进行优化。

那么,如何尽可能的避免死锁呢?

  • 以固定的顺序访问表和行。即按顺序申请锁,这样就不会造成互相等待的场面。
  • 大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
  • 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
  • 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。
  • 为表添加合理的索引。如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。

数据库中的乐观锁和悲观锁有什么区别,各适用于什么场景

悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念。

  • 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

  • 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

  • 两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

    悲观锁和乐观锁大部分场景下差异不大,一些独特场景下有一些差别,一般我们可以从如下几个方面来判断:

  • 响应速度:如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁

  • 冲突频率:如果冲突频率非常高,建议采用悲观锁,保证成功率,如果冲突频率大,乐观锁会需要多次重试才能成功,代价比较大

  • 重试代价:如果重试代价大,建议采用悲观锁

请结合你的开发经历,谈谈数据库中的乐观锁和悲观锁是具体如何被应用的?

以商品扣减为例,悲观锁和乐观锁的实现分别为:
要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。我们可以使用命令设置MySQL为非autocommit模式【即使用事务】:

   set autocommit=0;
   //设置完autocommit后,我们就可以执行我们的正常业务了。具体如下:
   //开始事务
   begin;/begin work;/start transaction; (三者选一就可以)
   //查询出商品信息
   select status from items where id=10000 for update;
   //根据商品信息生成订单
   insert into orders (id,item_id) values (null,10000);
   //修改商品status为2
   update items set status=2 where id=10000;
   //提交事务
   commit;

注:上面的begin/commit为事务的开始和结束,因为在前一步我们关闭了mysql的autocommit,所以需要手动控制事务的提交,在这里就不细表了。

乐观锁实现为:
以mysql InnoDB存储引擎为例,还是拿之前的例子商品表items表中有一个字段status,status=1表示该商品未被下单,status=2表示该商品已经被下单,那么我们对每个商品下单前必须确保此商品的status=1。假设有一件商品,其id为10000;
下单操作:

  //查询出商品信息
  select (status,version) from items where id=#{id}
  //根据商品信息生成订单
  //修改商品status为2
  update items set status=2,version=version+1 where id=#{id} and version=#{version};

若挑选以库存数作为乐观锁,则失败率会小很多,如下(用乐观锁方式扣减库存,确保有库存即可):

  update item 
  set     
  quantity=quantity-#sub_quantity# 
  where     
      item_id = #id#     
      and quantity-#sub_quantity# > 0

【备注】用户注册,如何防止重复写入相同用户?悲观锁是一种方式,如何实现?另外一种方式是使用唯一索引?
【备注】for Update加锁详解
举个例子: 假设商品表单products 内有一个存放商品数量的quantity ,在订单成立之前必须先确定quantity 商品数量是否足够(quantity>0) ,然后才把数量更新为1。
不安全的做法:

  SELECT quantity FROM products WHERE id=3; 
  UPDATE products SET quantity = 1 WHERE id=3;

为什么不安全呢?
少量的状况下或许不会有问题,但是大量的数据存取「铁定」会出问题。
如果我们需要在quantity>0 的情况下才能扣库存,假设程序在第一行SELECT 读到的quantity 是2 ,看起来数字没有错,但是当MySQL 正准备要UPDATE 的时候,可能已经有人把库存扣成0 了,但是程序却浑然不知,将错就错的UPDATE 下去了。
因此必须透过的事务机制来确保读取及提交的数据都是正确的。
于是我们在MySQL 就可以这样测试:

  SET AUTOCOMMIT=0; 
  BEGIN WORK; 
  SELECT quantity FROM products WHERE id=3 FOR UPDATE;
  //此时products 数据中id=3 的数据被锁住(注3),其它事务必须等待此次事务 提交后才能执行
  //SELECT * FROM products WHERE id=3 FOR UPDATE 如此可以确保quantity 在别的事务读到的数字是正确的。 
  //代码如下:
  UPDATE products SET quantity = '1' WHERE id=3 ; 
  COMMIT;

Mysql日志相关

此处了解即可,mysql内部日志主要区分为:
事务日志:
工作模式:基于InnoDB存储引擎的MySQL之所以可以从崩溃中恢复,正是依赖于事务日志,当数据库实例宕机后,重启时MySQL会自行检查事务日志,然后依次处理;
事务日志分为redo log和undo log两种:
(1)、对于事务日志中未正常提交的事务,则会记录到undo log中,因为事务未正确执行完,因此必须回滚,从而保证数据一致性
(2)、对于事务日志中已正常提交但未同步到持久化存储上时,则会记录到redo log中,因此MySQL会重新执行一遍事务,然后让数据存储到磁盘上,从而保证数据一致性

二进制日志
MySQL中的二进制日志(binary log)是一个二进制文件,主要用于记录可能引起数据库内容更改的SQL语句或数据行记录,例如新增(Insert)、更新(Update)、删除(Delete)、授权信息变更(Grant Change)等,除记录这些外,还会记录变更语句的发生时间、执行时长、操作数据等额外信息,但是它不会记录诸如Select、Show等这些不会引起数据修改的SQL语句。
binary log 主要用于主从复制等集群模式

慢日志与错误日志
(errlog)错误日志,作用:Mysql本身启动,停止,运行期间发生的错误信息
(slow query log)慢查询日志,  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功

更多日志种类后续慢慢了解即可

Linux

linux常用命令有哪些,分别举例

显示文件目录命令ls 如ls
改变当前目录命令cd 如cd /home
建立子目录mkdir 如mkdir xiong
删除子目录命令rmdir 如rmdir /mnt/cdrom
删除文件命令rm 如rm /ucdos.bat
文件复制命令cp 如cp /ucdos /fox
获取帮助信息命令man 如man ls
显示文件的内容less 如less mwm.lx
重定向与管道type 如type readme>>direct,将文件readme的内容追加到文direct中,例如ps -ef|grep java

linux下如何查看网络端口状态(netstat),如何查看内存使用情况(top)

查询3306端口占用情况的linux指令如何写?

netstat -an | grep 3306

linux中查看某个java进行的进程号pid,如何操作呢?

ps -ef|grep 实际的java进程名称

原创文章,作者:sunnyman218,如若转载,请注明出处:https://blog.ytso.com/273923.html

(0)
上一篇 2022年7月13日
下一篇 2022年7月13日

相关推荐

发表回复

登录后才能评论