范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Mysql索引,事务和锁

  一、索引
  1、存储引擎:InnoDB, MyISAM,Memory.
  2、InnoDB:数据会存储到磁盘上,在真正处理数据时,需要先将数据加载到内存,表中读取某些记录时,
  InnoDB不需要一条一条的把记录从磁盘上读出来,InnoDB采取的方式是:将数据划分位若干个页,以
  页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为16kb,也就是说,当需要从磁盘
  中读取数据时,每次最少从磁盘读取16kb的内容到内存,每次最少也会把内存中的16kb内容写到磁盘中。
  3、页是InnoDB管理存储空间的基本单位,一个页的默认大小是16kb
  show global status like "Innodb_page_size"; 页结构: 名称               中文名称             占用空间        描述 File Header        文件头部              38字节       页的一些通用信息 Page Header        页面头部              56字节       数据页专有的一些信息 Infimum+Supremum   最小记录和最大记录     26字节       两个虚拟的行记录 User Records       用户记录              不确定       实际存储的行记录内容 Free Space         空闲空间              不确定       页中尚未使用的空间 Page Director      页面目录              不确定       页中某些记录的相对位置(当一行的数据量很小时,会出现一页存储更多的记录数,查询时通过页目录可以提高查询效率) File Trailer       文件尾部              8字节        校验页是否完整
  4、InnoDB行格式
  一行记录可以以不同的格式存在Innodb中,行格式分别是Compact,Redundant,Dynamic和Compressed
  可以在创建或修改表的语句中指定行格式:
  create table 表名(列信息) ROW_FORMAT=行格式名称
  ALTER TABLE 表名 ROW_FORMAT=行格式名称 Compact行格式:     变长字段长度列表|NULL标志位|记录头信息|列1数据|列2数据...      1)MySQL支持一些变长的数据类型,比如VARCHAR(M)、 VARBINARY(M)、 TEXT类型,BLOB类型,这些数据类型 修饰列称为变长字段,变长字段中存储多少字节的数据不是固定的,所以我们在存储真实数据的时候需要顺便把 这些数据占用的字节数也存起来。在Compact行格式中,把所有变长字段的真实数据占用的字节长度都存放在记 录的开头部位,从而形成一个变长字段长度列表。 CHAR是一种固定长度的类型,VARCHAR则是一种可变长度的类型。 VARCHAR(M),M代表最大能存多少个字符。 ( MySQL5.0.3以前是字节,以后就是字符);     2)Compact行格式会把可以为NULL的列统一管理起来,存一个标记为在NULL值列表中,如果表中没有允许存储  NULL 的列,则 NULL值列表也不存在了。二进制位的值为1时,代表该列的值为NULL。二进制位的值为0时,代表该列的值不为NULL     3)除了变长字段长度列表、 NULL值列表之外,还有一个用于描述记录的记录头信息,它是由固定的5个字节组成。       5个字节也就是40个二进制位,不同的位代表不同的意思,如:       名称               大小(单位: 位:bit))         描述       预留位1             1                                         没有使用       预留位2             1                                         没有使用       delete_mask     1                                         标记该记录是否被删除       min_rec_mask   1                                        B+树的每层非叶子节点中的最小记录都会添加该标记       n_owned           4                                        表示当前记录拥有的记录数       heap_no           13                                       表示当前记录在记录堆的位置信息       record_type      3                                        表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录       next_record     16                                        表示下一条记录的相对位置     4)记录的真实数据除了我们自己定义的列的数据以外,还会有三个隐藏列      列名                 是否必须        占用空间   描述      row_id                  否              6字节       行ID,唯一标识一条记录      transaction_id      是               6字节      事务ID      roll_pointer          是              7字节       回滚指针      实际上这几个列的真正名称其实是:DB_ROW_ID、 DB_TRX_ID、 DB_ROLL_PTR       一个表没有手动定义主键,则会选取一个Unique键作为主键,如果连Unique键都没有定义的话,则会为表默      认添加一个名为row_id的隐藏列作为主键。所以row_id是在没有自定义主键以及Unique键的情况下才会存在      的。       5)VARCHAR(M)类型的列最多可以占用65535个字节。其中的M代表该类型最多存储的字符数量,如果我们使用        ascii字符集的话,一个字符就代表一个字节,我们看看VARCHAR(65535)是否可用:        mysql> CREATE TABLE varchar_size_demo(        -> c VARCHAR(65535)        -> ) CHARSET=ascii ROW_FORMAT=Compact;        ERROR 1118 (42000): Row size too large. The maximum row size for the used table type,        not counting BLOBs, is 65535. This includes storage overhead, check the manual. You        have to change some columns to TEXT or BLOBs        mysql>        报错信息表达的意思是:MySQL对一条记录占用的最大存储空间是有限制的,除BLOB或者TEXT类型的列之外,        其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字节。这个65535个字节        除了列本身的数据之外,还包括一些其他的数据,比如说我们为了存储一个VARCHAR(M)类型的列,其实需要占        用3部分存储空间:        1. 真实数据        2. 变长字段真实数据的长度        3. NULL值标识        如果该VARCHAR类型的列没有NOT NULL属性,那最多只能存储65532个字节的数据,因为变长字段的长度占用        2个字节,NULL值标识需要占用1个字节。        mysql> CREATE TABLE varchar_size_demo(        -> c VARCHAR(65532)        -> ) CHARSET=ascii ROW_FORMAT=Compact;        Query OK, 0 rows affected (0.02 sec)        CREATE TABLE varchar_size_demo(        c VARCHAR(65533) not null        ) CHARSET=ascii ROW_FORMAT=Compact;        Query OK, 0 rows affected (0.02 sec)       6)一个页的大小一般是16KB,也就是16384字节,而一个VARCHAR(M)类型的列就最多可以存储65533个字节,这        样就可能出现一个页存放不了一条记录。        在Compact和Reduntant行格式中,对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的一部分        数据,把剩余的数据分散存储在几个其他的页中,然后记录的真实数据处用20个字节存储指向这些页的地址(当        然这20个字节中还包括这些分散在其他页面中的数据的占用的字节数),从而可以找到剩余数据所在的页.  Dynamic和Compressed行格式:      这两种行格式类似于COMPACT行格式,只不过在处理行溢出数据时有点儿分歧,它们不会在记录的真实数据处      存储一部分数据,而是把所有的数据都存储到其他页面中,只在记录的真实数据处存储其他页面的地址。另外,      Compressed行格式会采用压缩算法对页面进行压缩。
  5、聚族索引: 聚簇索引的特点:  1. 按主键值的大小进行记录和页的排序: 数据页(叶子节点)里的记录是按照主键值从小到大排序的一个单向链表。 数据页(叶子节点)之间也是是按照主键值从小到大排序的一个双向链表。 B+树中同一个层的页目录也是按照主键值从小到大排序的一个双向链表。  2. B+树的叶子节点存储的是完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。 具有这两种特性的B+树称为聚簇索引,所有完整的用户记录都存放在这个聚簇索引的叶子节点处。这种聚簇索引 并不需要我们在MySQL语句中显式的使用INDEX语句去创建。 InnoDB存储引擎会自动的为我们创建聚簇索引。 在InnoDB存储引擎中,聚簇索引就是数据的存储方式(所有的用户记录都存储在了叶子节点),也就是所谓的索 引即数据,数据即索引。
  6、二级索引: 聚簇索引只能在搜索条件是主键值时才能发挥作用,因为B+树中的数据都是按照主键进行排序的。当我们想以别 的列作为搜索条件时我们可以多建几棵B+树,不同的B+树中的数据采用不同的排序规则。 二级索引与聚簇索引有几处不同: 1. 按指定的索引列的值来进行排序 2. 叶子节点存储的不是完整的用户记录,而只是索引列+主键。 3. 目录项记录中不是主键+页号,变成了索引列+页号。 4. 在对二级索引进行查找数据时,需要根据主键值去聚簇索引中再查找一遍完整的用户记录,这个过程叫做回表。
  7、联合索引: 以多个列的大小为排序规则建立的B+树称为联合索引,本质上也是一个二级索引。
  8、B+树索引: 1. 每个索引都对应一棵B+树。用户记录都存储在B+树的叶子节点,所有目录记录都存储在非叶子节点。 2. InnoDB存储引擎会自动为主键(如果没有它会自动帮我们添加)建立聚簇索引,聚簇索引的叶子节点包 含完整的用户记录。 3. 可以为指定的列建立二级索引,二级索引的叶子节点包含的用户记录由索引列 + 主键组成,所以如果想 通过二级索引来查找完整的用户记录的话,需要通过回表操作,也就是在通过二级索引找到主键值之后再 到聚簇索引中查找完整的用户记录。 4. B+树中每层节点都是按照索引列值从小到大的顺序排序而组成了双向链表,而且每个页内的记录(不论 是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序而形成了一个单链表。如果是联合索引 的话,则页面和记录先按照联合索引前边的列排序,如果该列值相同,再按照联合索引后边的列排序。 5. 通过索引查找记录是从B+树的根节点开始,一层一层向下搜索。由于每个页面都按照索引列的值建立了 页目录,所以在这些页面中的查找非常快。
  9、根页: 创建表时,mysql先创建一页,当插入的数据第一页放不下时,会把第一页复制一份,然后新开辟新的一页存新插入的数据,原来的第一页改为根页。
  10、b+树
  11、mysql 数据存储结构
  二、查询优化1、开启查询优化器日志: set optimizer_trace="enabled=on"; -- 开启 -- 执行sql -- 查看日志信息: select * from information_schema.OPTIMIZER_TRACE; -- 关闭 set optimizer_trace="enabled=off";  2、常量传递(constant_propagation) a=1 and b>a 上面这个sql可以转换为: a = 1 and b > 1  3、等值传递(equality_propagation) a = b and b = c and c = 5 上面这个sql可以转换为: a = 5 and b = 5 and c = 5  4、移除没用的条件(trivial_condition_removal) a = 1 and 1 = 1 上面这个sql可以转换为: a = 1  5、成本: 一个查询可以有不同的执行方案,可以选择某个索引进行查询,也可以选择全表扫描,查询优化器会选择其中成 本最低的方案去执行查询。  6、IO成本: InnoDB存储引擎都是将数据和索引都存储到磁盘上的,当我们想查询表中的记录时,需要先把数据或者索引加载 到内存中然后再操作。这个从磁盘到内存这个加载的过程损耗的时间称之为I/O成本。  7、CPU成本: 读取以及检测记录是否满足对应的搜索条件、对结果集进行排序等这些操作损耗的时间称之为CPU成本。  InnoDB存储引擎规定读取一个页面花费的成本默认是1.0,读取以及检测一条记录是否符合搜索条件的成本默 认是0.2。 三、事务和锁1、事务 原子性(Atomicity)、隔离性(Isolation)、一致性(Consistency)、持久性(Durability)     -- 显示开启事务(提交、回滚)     begin; -- start transaction;     savepoint p1; -- 保存点(名称)     commit; -- rollback; ROLLBACK TO p1;
  2、隔离级别: 1未提交读(read uncommitted):一个事务可以读到其他事务还没有提交的数据,会出现脏读  2)已提交读(read committed):一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每对该数据进行一次修改并提交后,该事                             务都能查询得到最新值,会出现不可重复读、幻读。                             如果一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,原先                             的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来,这就是幻读。  3)可重复读(repeatable read):一个事务第一次读过某条记录后,即使其他事务修改了该记录的值并且提交,该事务之后再读该条记录时,读到                             的仍是第一次读到的值,而不是每次都读到不同的数据,这就是可重复读,这种隔离级别解决了不可重复,但是                             还是会出现幻读。  4)串行化(serializable): 以上3种隔离级别都允许对同一条记录同时进行读-读、读-写、写-读的并发操作,如果我们不允许读-写、写-读                          的并发操作,可以使用SERIALIZABLE隔离级别,这种隔离基金因为对同一条记录的操作都是串行的,所以不会                          出现脏读、幻读等现象。   总结:    READ UNCOMMITTED隔离级别下,可能发生脏读 脏读、 不可重复读和和幻读问题。    READ COMMITTED隔离级别下,可能发生不可重复读 不可重复读和**幻读问题,但是不会发生 问题,但是不会发生脏读问题。    REPEATABLE READ隔离级别下,可能发生幻读 幻读问题,不会发生脏读 脏读和不可重复读的问题。    SERIALIZABLE隔离级别下,各种问题都不可以发生。    注意:这四种隔离级别是SQL的标准定义,不同的数据库会有不同的实现,特别需要注意的是    MySQL在在REPEATABLE READ隔离级别下,是可以禁止幻读问题的发生的 隔离级别下,是可以禁止幻读问题的发生的
  3、版本链:对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们
  创建的表中有主键或者非NULL唯一键时都不会包含row_id列):
  trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
  roll_pointer:每次对某条记录进行改动时,这个隐藏列会存一个指针,可以通过这个指针找到该记
  录修改前的信息。
  4、ReadView:对于使用READ UNCOMMITTED隔离级别的事务来说,直接读取记录的最新版本就好了,对于使用
  SERIALIZABLE隔离级别的事务来说,使用加锁的方式来访问记录。对于使用READ COMMITTED和
  REPEATABLE READ隔离级别的事务来说,就需要用到我们上边所说的版本链了,核心问题就是:需要判断一下
  版本链中的哪个版本是当前事务可见的
  ReadView中主要包含4个比较重要的内容: 1. m_ids:表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。 2. min_trx_id:表示在生成ReadView时当前系统中活跃的读写事务中最小的事务id,也就是m_ids中的最小 值。 3. max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的id值。 4. creator_trx_id:表示生成该ReadView的事务的事务id。 注意max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三个事务,之 后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,min_trx_id的值就是1, max_trx_id的值就是4。  有了这个ReadView,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见: 如果被访问版本的trx_id属性值与ReadView中的creator_trx_id值相同,意味着当前事务在访问它自     己修改过的记录,所以该版本可以被当前事务访问。 如果被访问版本的trx_id属性值小于ReadView中的min_trx_id值,表明生成该版本的事务在当前事     务生成ReadView前已经提交,所以该版本可以被当前事务访问。 如果被访问版本的trx_id属性值大于ReadView中的max_trx_id值,表明生成该版本的事务在当前事     务生成ReadView后才开启,所以该版本不可以被当前事务访问。 如果被访问版本的trx_id属性值在ReadView的min_trx_id和max_trx_id之间,那就需要判断一下     trx_id属性值是不是在m_ids列表中,如果在,说明创建ReadView时生成该版本的事务还是活跃     的,该版本不可以被访问;如果不在,说明创建ReadView时生成该版本的事务已经被提交,该版     本可以被访问。  READ COMMITTED的实现方式:     每次读取数据前都生成一个ReadView。 REPEATABLE READ实现方式:     在第一次读取数据时生成一个ReadView。
  5、MVCC(版本链+read view)总结:
  MVCC(Multi-Version Concurrency Control ,多版本并发控制)指的就是在使用READ COMMITTD、
  REPEATABLE READ这两种隔离级别的事务在执行普通的SEELCT操作时访问记录的版本链的过程。可以使不同
  事务的读-写、写-读操作并发执行,从而提升系统性能。 READ COMMITTD、 REPEATABLE READ这两个隔离级
  别的一个很大不同就是:生成ReadView的时机不同,READ COMMITTD在每一次进行普通SELECT操作前都会
  生成一个ReadView,而REPEATABLE READ只在第一次进行普通SELECT操作前生成一个ReadView,之后的查
  询操作都重复使用这个ReadView就好了
  6、锁
  读锁:共享锁、 Shared Locks、 S锁
  写锁:排他锁、 Exclusive Locks、 X锁 1)读操作:     对于普通 SELECT 语句,InnoDB 不会加任何锁     select ... lock in share model;     将查找到的数据加上一个S锁,允许其他事务继续获取这些记录的S锁,不能获取这些记录的X锁(会阻塞)      select ... for update;     将查找到的数据加上一个X锁,不允许其他事务获取这些记录的S锁和X锁。  2)写操作:     DELETE:删除一条数据时,先对记录加X锁,再执行删除操作     INSERT:插入一条记录时,会先加隐式锁 隐式锁来保护这条新插入的记录在本事务提交前不被别的事务访问到。     UPDATE:如果被更新的列,修改前后没有导致存储空间变化,那么会先给记录加X锁,再直接对记录进行修改。             如果被更新的列,修改前后导致存储空间发生了变化,那么会先给记录加X锁,然后将记录删掉,再Insert一条新记录      隐式锁:一个事务插入一条记录后,还未提交,这条记录会保存本次事务id,而其他事务如果想来读取这个记     录会发现事务id不对应,所以相当于在插入一条记录时,隐式的给这条记录加了一把隐式锁。
  7、行锁和表锁: 1)行锁:     LOCK_REC_NOT_GAP:单个行记录上的锁     LOCK_GAP:间隙锁,锁定一个范围,但不包括记录本身。 GAP锁的目的,是为了防止同一事务                     的两次当前读,出现幻读的情况。      LOCK_ORDINARY:锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。   2)间隙锁(LOCK_GAP、GAP锁):    a、Read Committed级别下:     主键查询:     +---+------+------+------+------+     | a | b | c | d | e |     +---+------+------+------+------+     | 1 | 1 | 1 | 1 | 1 |     +---+------+------+------+------+         begin;         select * from t1 where a = 1 for update;         select * from t1 where a = 1 for update; -- 阻塞         select * from t1 where a = 2 for update; -- 不阻塞         查询使用的是主键时,只需要在主键值对应的那一个条数据加锁即可。      唯一索引查询:    +---+------+------+------+------+    | a | b | c | d | e |    +---+------+------+------+------+    | 1 | 1 | 1 | 1 | 1 |    +---+------+------+------+------+         begin;          select * from t1 where b = 1 for update;          select * from t1 where b = 1 for update; -- 会阻塞          select * from t1 where b = 2 for update; -- 不阻塞         查询使用的是唯一索引时,只需要对查询值所对应的唯一索引记录项和对应的聚集索引上的项加锁即可。      普通索引查询:     +----+------+------+------+------+     | a | b | c | d | e |     +----+------+------+------+------+     | 6 | 6 | 1 | 4 | 6 |     | 12| 12 | 1 | 1 | 6 |     +----+------+------+------+------+         begin;         select * from t1 where e = "6" for update;         select * from t1 where a = 6 for update; -- 阻塞         select * from t1 where a = 12 for update; -- 阻塞         select * from t1 where a = 1 for update; -- 不阻塞         select * from t1 where a = 2 for update; -- 不阻塞         insert t1(b,c,d,e) values(20,1,1,"51"); -- 不阻塞         insert t1(b,c,d,e) values(21,1,1,"61"); -- 不阻塞     查询使用的是普通索引时,会对满足条件的索引记录都加上锁,同时对这些索引记录对应的聚集索引上的     项也加锁。      没有使用索引:         +----+------+------+------+------+         | a | b | c | d | e |         +----+------+------+------+------+         | 1 | 1 | 1 | 1 | 1 |         | 2 | 2 | 1 | 2 | 2 |         | 4 | 3 | 1 | 1 | 4 |         | 6 | 6 | 1 | 4 | 6 |         | 8 | 8 | 1 | 8 | 8 |         | 10 | 10 | 1 | 2 | 10 |         | 12 | 12 | 1 | 1 | 6 |         +----+------+------+------+------+         begin;         select * from t1 where c = "1" for update;          select * from t1 where a = 1 for update; --阻塞         select * from t1 where a = 2 for update; -- 阻塞         select * from t1 where a = 3 for update; -- 不阻塞         select * from t1 where a = 7 for update; --不阻塞         查询的时候没有走索引,也只会对满足条件的记录加锁。     b、Repeatable Read级别下:        查询使用主键:和ReadCommitted级别一样。       查询使用唯一索引:和ReadCommitted级别一样。       查询使用普通索引:         mysql> begin;         Query OK, 0 rows affected (0.00 sec)         mysql> select * from t1 where e = "6" for update;         +----+------+------+------+------+         | a | b | c | d | e |         +----+------+------+------+------+         | 6 | 6 | 1 | 4 | 6 |         | 12 | 12 | 1 | 1 | 6 |         +----+------+------+------+------+         2 rows in set (0.00 sec)      mysql> select * from t1 where a = 6 for update; -- 阻塞     mysql> select * from t1 where a = 12 for update; -- 阻塞     mysql> select * from t1 where a = 1 for update; -- 不阻塞     mysql> select * from t1 where a = 2 for update; -- 不阻塞     mysql> insert t1(b,c,d,e) values(20,1,1,"51"); -- 阻塞     mysql> insert t1(b,c,d,e) values(21,1,1,"61"); -- 阻塞     总结:REPEATABLE READ级别可以解决幻读,解决的方式就是加了GAP锁。      查询没有使用索引:      mysql> begin;     Query OK, 0 rows affected (0.00 sec)     mysql> select * from t1 where c = "1" for update;     +----+------+------+------+------+     | a  | b  | c | d | e  |     +----+------+------+------+------+     | 1  | 1  | 1 | 1 | 1  |     | 2  | 2  | 1 | 2 | 2  |     | 4  | 3  | 1 | 1 | 4  |     | 6  | 6  | 1 | 4 | 6  |     | 8  | 8  | 1 | 8 | 8  |     | 10 | 10 | 1 | 2 | 10 |     | 12 | 12 | 1 | 1 | 6  |     +----+------+------+------+------+     7 rows in set (0.00 sec)      mysql> select * from t1 where a = 1 for update; -- 会阻塞     mysql> select * from t1 where a = 2 for update; -- 会阻塞     mysql> select * from t1 where a = 3 for update; -- 不会阻塞     mysql> select * from t1 where a = 7 for update; -- 会阻塞(在Read Committed下不会阻塞,跟解决幻读有关系)     总结:查询的时候没有走索引,会对表中所有的记录以及间隙加锁。
  8、表锁: 表级别S锁,X锁。     在对某个表执行SELECT、 INSERT、 DELETE、 UPDATE语句时,InnoDB存储引擎是不会为这个表添加表级别的     S锁或者X锁的 在对某个表执行ALTER TABLE、 DROP TABLE这些DDL语句时,其他事务对这个表执行SELECT、 INSERT、 DELETE、 UPDATE的语句会发生阻塞,或者,某个事务对某个表执行SELECT、 INSERT、 DELETE、 UPDATE语 句时,其他事务对这个表执行DDL语句也会发生阻塞。这个过程是通过使用的元数据锁(英文名:Metadata Locks,简称MDL)来实现的,并不是使用的表级别的S锁和X锁 LOCK TABLES t1 READ:对表t1加表级别的S锁。 LOCK TABLES t1 WRITE:对表t1加表级别的S锁  尽量不用这两种方式去加锁,因为InnoDB的优点就是行锁,所以尽量使用行锁,性能更高。
  9、
  IS锁:意向共享锁、 Intention Shared
  Lock。当事务准备在某条记录上加S锁时,需要先在表级别
  加一个IS锁。
  IX锁:意向排他锁、 Intention Exclusive Lock。当事务准备在某条记录上加X锁时,需要先在表级
  别加一个IX锁
  IS、 IX锁是表级锁,它们的提出仅仅为了在之后加表级别的S锁和X锁时可以快速判断表中的记录是否被上锁,以
  避免用遍历的方式来查看表中有没有上锁的记录
  10、AUTO-INC锁:
  在执行插入语句时就在表级别加一个AUTO-INC锁,然后为每条待插入记录的AUTO_INCREMENT
  修饰的列分配递增的值,在该语句执行结束后,再把AUTO-INC锁释放掉。这样一个事务在持有
  AUTO-INC锁的过程中,其他事务的插入语句都要被阻塞,可以保证一个语句中分配的递增值是连
  续的。
  采用一个轻量级的锁,在为插入语句生成AUTO_INCREMENT修饰的列的值时获取一下这个轻量级
  锁,然后生成本次插入语句需要用到的AUTO_INCREMENT列的值之后,就把该轻量级锁释放掉,
  并不需要等到整个插入语句执行完才释放锁。 系统变量innodb_autoinc_lock_mode: innodb_autoinc_lock_mode值为0:采用AUTO-INC锁。 innodb_autoinc_lock_mode值为2:采用轻量级锁。 当innodb_autoinc_lock_mode值为1:当插入记录数不确定是采用AUTO-INC锁,当插入记录数确 定时采用轻量级锁
  11、悲观锁:
  悲观锁用的就是数据库的行锁,认为数据库会发生并发冲突,直接上来就把数据锁住,其他事务不能修改,直至
  提交了当前事务。
  12、乐观锁:
  乐观锁其实是一种思想,认为不会锁定的情况下去更新数据,如果发现不对劲,才不更新(回滚)。在数据库中往
  往添加一个version字段来实现。
  13、死锁: session1: mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from t1 where a =1 for update; -- 第一步 +---+------+------+------+------+ | a | b | c | d | e | +---+------+------+------+------+ | 1 | 1 | 1 | 1 | 1 | +---+------+------+------+------+ 1 row in set (0.00 sec) mysql> update t1 set c = 2 where a = 4; -- 第三步 开始会阻塞 ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction  session2:  mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> delete from t1 where a = 4; -- 第二步 Query OK, 1 row affected (0.00 sec) mysql> delete fromt t1 where a = 1; -- 第四步,阻塞产生死锁,mysql有死锁检测机制,让死锁中断
  14、避免死锁:
  以固定的顺序访问表和行
  大事务拆小,大事务更容易产生死锁
  在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率
  降低隔离级别(下下签)
  为表添加合理的索引。

龙岗平湖跨境电商产业园项目将打造深圳跨境电商总部基地2月6日,龙岗平湖跨境电商产业园优质产业空间试点项目(下称平湖试点项目)用地由深圳市特区建工集团有限公司成功摘得。该项目是龙岗区继深圳首个优质产业空间试点深圳宝龙专精特新产业园之后我们的故事我曾在童年恣意玩耍,体会过在户外奔跑的乐趣,所以不愿孩子们被锁在城市的高楼大厦里。我要为孩子们创造更生动快乐的童年。HUDIHUDI的诞生在手游里匹配到了一个小孩子,我以为现在的小文旅复苏仿真恐龙制造企业深挖潜力记者获悉,大安区规模以上企业目前已基本复工复产,多数企业订单较去年同期均有增长,个别企业呈现爆发式增长态势。6日,记者走进代表性企业自贡市恐龙景观艺术有限公司,实地探访企业复工第一出境游火爆重启,仍需谨防倒春寒首发高端泰国跟团游,余位5,预定从速。随着出境游重启,出境领队的朋友圈纷纷开张营业,逐渐恢复往日的热闹。春节前夕,文旅部发布通知,自2023年2月6日起,试点恢复全国旅行社及在线旅全国射击冠军赛,闽将朱晓忠摘银!祝贺!闽将朱晓忠在2023年全国射击冠军赛中获得男子10米气步枪排名赛亚军2023年全国射击冠军赛(步手枪项目)日前在西安开赛。这也是2023年射击项目国际比赛选拔赛第一阶段的第一强信心开新局山东日照市场抬头订单在手开年以来,我们的各类订单已经排到了下半年,产量也在不断增加,实现开门红。说到生产情况,日照京杭林产家具有限公司企管部经理孙媛媛喜上眉梢。京杭林产是山东省日照市岚山区木材产业链上精深领奖通知!乐跑日照2023年癸卯兔新年贺岁线上跑开始领奖大众网海报新闻记者鞠颖日照报道近日,由日照市马拉松协会大众网日照主办的全新兔破跑迎新年乐跑日照2023年癸卯兔新年贺岁线上跑已圆满落下帷幕。据后台统计,截至记者发稿前,本次赛事活动一个典型的数字化工厂建设书(简要)注数字化工厂建设可大可小,可深可浅,根据具体业务定义即可。数字化工厂的目标是软件定义数据驱动。即,按照设定好的模型,根据业务的动态数据,驱动业务过程计划投料和控制。数字化工厂建设,贝尔戈米对比那不勒斯国米应做得更好什克里尼亚尔难以取代直播吧2月9日讯在接受米兰体育报的采访时,国米传奇后卫贝佩贝尔戈米认为,蓝黑军团本赛季的表现令人失望,因为他们没能在意甲积分榜上跟上那不勒斯的步伐。贝尔戈米还指出,为什克里尼亚尔寻我国当今保存最完好的北宋城,竟在江西第二大城市,你去过吗?郁孤台下清江水,中间多少行人泪。这是宋代文武之才辛弃疾菩萨蛮书江西造口壁中的一句词,这句词也成为了本次的目的地,江南宋城。一座赣州城,半部宋代史。赣州,别称虔州,江西南大门,是宋代春天,衣橱里的这几件经典单品,搭配好了真的很绝嗨,我是柒作作。春天就这样悄无声息地来了,我们是不是还没有开始给自己准备春天的衣服?不用着急,其实打开衣橱,你会发现,原来自己并不缺衣服,只是缺少会搭配灵感,或许衣橱里的这几件经典
新手宝妈必看!宝宝添加辅食手册夏天到了,越来越多新鲜食材上市了,非常时候给宝宝做辅食增加营养,最近很多新手宝妈咨询,给宝宝增加辅食时候有顺序吗?有没有什么原则?注意事项是什么等,确实,给宝宝添加辅食是个大事,每重新审视炸窝app的爆品要素爆品战略这本书,开始主要是从公司电商业务角度去看的,也可以完全审视炸窝app。最后一章,爆品干掉爆品,人人网曾经是电脑时代的一款爆品,是大学生必上的社交网站,也被称为中国版的Fac1。2亿年前化石提供重要线索揭示哺乳动物听觉器官演化奥秘九佛堂传夔兽化石九佛堂传夔兽生态复原图名词真兽类真兽类即真兽亚纲,又叫有胎盘亚纲,包括已绝灭和现生的有胎盘哺乳动物,共分为30余目,约占现存哺乳动物的95,分布在全世界的各个角落。远古爆炸产生的鸿蒙之气,正从地核泄露,每吨高达30亿美元最近科学研究表明,一种极为珍贵的气体,正在不断地从我们的地球中流失掉,它就是氦3。这种气体极其珍贵,仅在地球的内核中少量存在,其气体含量,只占地球氦含量的0。0001。这种气体之所厄尔尼诺气候模式厄尔尼诺是一种反复出现的气候模式,在陆地和海洋上都会引起剧烈的天气变化。这些变化始于赤道太平洋,海洋温度比平常高。在非厄尔尼诺年份,赤道信风向西吹过太平洋,通常将温暖的海水带向亚洲红米k50电竞版降价了,小米旗下唯一一款3k以下的骁龙8旗舰机据了解,红米50电竞版降价了,现京东预估到手机2899元,这要比首发价的3299元要便宜400元。这会是小米旗下唯一一款3000元以下的骁龙8旗舰机,也是同等价位唯一一款支持百瓦超折叠屏手机的优点和缺点,你会选择折叠屏手机吗折叠屏手机的想法在2018年向手机用户推出。各大手机厂商推出了各种样式和形式的折叠屏手机。GalaxyFold(2019年2月)华为MateX(2019年2月)摩托罗拉RAZR(2其他品牌都在吹,只有中兴在坚持!终于重新崛起了关于屏下摄像头技术,从前两年就开始研发了,不过当时仅仅处于初步阶段,并且当时并没有太强大的成果。但这项技术对于全面屏算是最合适的方案,当时对于这个技术可以说是非常火热,各大厂商纷纷奥沙利文3杆破百,125领先特鲁姆普,两度与裁判发生争执事件5月1日,2022年斯诺克世锦赛进行了决赛首日两个阶段的角逐,赛会2号种子六冠王火箭奥沙利文与4号种子特鲁姆普上演强强对话。最终在两个阶段17局的较量中,奥沙利文火力全开,凭借着两巴菲特向芒格介绍段永平段永平卖的手机销量和苹果差不多Tech星球5月2日消息,段永平今日在社交平台发文称,他去吃晚餐的时候在餐厅里见到了巴菲特和芒格。巴菲特将他介绍给芒格,并介绍称段永平卖的手机销量和苹果差不多。巴菲特还表示,没有段部分iPhone6s用户不愿换新机,跟预算无关,有个原因很重要到2022年了,依然有很多iPhone6s用户不愿意换新机。对此,有人说这是因为iPhone6s用户手里没钱,换不了新款的iPhone手机。也有人说,iPhone6s用户能把iPh