建站学 - 轻松建站从此开始!

建站学-个人建站指南,网页制作,网站设计,网站制作教程

当前位置: 建站学 > 数据库 > Mysql 教程 >

理解MySQL——架构与概念(3)

时间:2009-10-18 23:00来源: 作者: 点击:
另外,如果删除索引i_index,则结果如下: 例 1-6 Session 1 Session 2 mysql drop index i_index on t; Query OK, 3 rows affected (0.25 sec) Records: 3Duplicates: 0Warnings: 0 mysql select * from t; +-----

另外,如果删除索引i_index,则结果如下:

1-6

Session 1

Session 2

mysql> drop index i_index on t;

Query OK, 3 rows affected (0.25 sec)

Records: 3 Duplicates: 0 Warnings: 0

mysql> select * from t;

+------+

| i    |

+------+

|    4 |

|   10 |

|    9 |

+------+

3 rows in set (0.00 sec)

 

 

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select i from t lock in share mode;

+------+

| i    |

+------+

|    4 |

|   10 |

|    9 |

+------+

3 rows in set (0.00 sec)

mysql> insert into t(i) values(8);

等待。。。

 

 

 另外,针对插入(INSERT)操作,只要多个事务不会在同一索引区间的同一个位置插入记录,它们就不用互相等待,这种情况可以称为插入意向间隙锁(insertion intention gap lock)。例如,索引记录的值为4和7,两个独立的事务分别插入5和6,仅管它们都持有4—7之间的间隙锁,但是它们不会相互阻塞。这可以提高事务的并发性。

 

1-7

Session 1

Session 2

mysql> select * from t;

+------+

| i    |

+------+

|    4 |

|   10 |

|    9 |

|    8 |

+------+

4 rows in set (0.00 sec)

 

mysql> create unique index i_index on t(i);

Query OK, 4 rows affected (0.34 sec)

Records: 4 Duplicates: 0 Warnings: 0

 

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

 

 

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t(i) values(5);

Query OK, 1 row affected (0.00 sec)

 

 

mysql> insert into t(i) values(5);

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> insert into t(i) values(6);

Query OK, 1 row affected (0.00 sec)

 间隙锁是可以显示关闭的,如果你将事务的隔离级别设为READ COMMITTED,或者打开innodb_locks_unsafe_for_binlog系统变量,间隙锁就会关闭。在这种情况下,查找或扫描索引仅会进行外键约束检查和重复键值检查。
此外,READ COMMITTED隔离级别和关闭nodb_locks_unsafe_for_binlog还有另外一个负作用:MySQL会释放掉不匹配Where条件的记录锁。例如,对于UPDATE语句,InnoDB只能进行“半一致性(semi_consistent)读”,所以,它会返回最新提交事务所做改变,从而产生不可重复读和幻像问题。

1.3.8、使用next-key lock防止幻像问题
例1-4展示了一个幻像问题。使用next-key锁的select语句可以解决幻像问题,但例1-4的之所以会产生总是在于唯一索引,使得select语句没有使用gap lock,而只使用了index-record lock。

1.4、存储引擎
插件式存储引擎是MySQL最重要特性之一,也是最不同于其它DBMS的地方。MySQL支持很多存储引擎,以适用于不同的应用需求,常用的包括MyISAM、InnoDB、BDB、MEMORY、MERGE、NDB Cluster等。其中,BDB和NDB Cluster提供事务支持。
MySQL默认的存储引擎为MyISAM,当然,创建表的时候可以指定其它的存储引擎,你可以在同一个数据库中对不同的表使用不同的存储引擎(这是非常强大而独特的特性)。可以通过SHOW TABLE STATUS命令查询表所使用的存储引擎,例如,查看mysql数据库的user表:

 

mysql> SHOW TABLE STATUS LIKE 'user' \G

*************************** 1. row ***************************

           Name: user

         Engine: MyISAM

        Version: 10

     Row_format: Dynamic

           Rows: 4

 Avg_row_length: 61

    Data_length: 244

Max_data_length: 281474976710655

   Index_length: 2048

      Data_free: 0

 Auto_increment: NULL

    Create_time: 2009-06-16 21:50:34

    Update_time: 2009-09-30 14:59:08

     Check_time: NULL

      Collation: utf8_bin

       Checksum: NULL

 Create_options:

        Comment: Users and global privileges

1 row in set (0.00 sec)

 Name:表的名称;
Engine:表使用的存储引擎;
Row_format:记录的格式。MyISAM支持三种不同的存储格式:静态(固定长度)表(默认格式)、动态表及压缩表。静态表的字段都是固定长度的,例如CHAR和INTEGER;动态表的字段可以是变长的,例如,VARCHAR或者BLOB。
Rows:表中记录的数量。
Avg_row_length:记录的平均长度(字节数);
Data_length:表中数据的全部字节数;
Max_data_length:表中数据最大的字节数;
Index_length:索引消耗的磁盘空间;
Data_free:对于MyISAM表,表示已经分配但还没有使用的空间;该空间包含以前删除的记录留下的空间,可以被INSERT操作重用。
Auto_increment:下一个自增的值。
Check_time:上次使用CHECK TABLE或myisamchk检查表的时间。

1.4.1、MyISAM
1.4.1.1、存储
MySQL的默认存储引擎,性能与功能的折中,包括全文索引(full-text index)、数据压缩,支持空间(GIS)数据,但是,不支持事务和行级锁。一般来说,MyISAM更适用于大量查询操作。如果你有大量的插入、删除操作,你应该选择InnoDB。
每个表包含3个文件:
(1).frm:表定义文件,对于其它存储引擎也一样。
(2).MYD文件:数据文件。
(3).MYI文件:索引文件。
可以在创建表时通过DATA DIRECTORY和INDEX DIRECTORY为数据文件和索引文件指定路径,它们可以位于不同目录。另外,MyISAM的存储格式是跨平台的,你可以将数据文件和索引文件从Intel平台拷贝到PPC或者SPARC平台。
5.0中,MyISAM的变长记录表默认处理256TB数据,使用6字节的指针来指向数据记录;而之前的版本使用默认的4字节指针,所以只能处理4GB数据。所有的版本都可以将指针增加到8字节指针,如果你想改变MyISAM表的指针的大小,可以通过设置MAX_ROWS和AVG_ROW_LENGTH来实现:
CREATE TABLE mytable (
   a    INTEGER  NOT NULL PRIMARY KEY,
   b    CHAR(18) NOT NULL
) MAX_ROWS = 1000000000 AVG_ROW_LENGTH = 32;
上面的例子中,MySQL将至少可以存储32GB的数据。可以查看一下表的信息:

mysql> SHOW TABLE STATUS LIKE 'mytable' \G

*************************** 1. row ***************************

           Name: mytable

         Engine: MyISAM

     Row_format: Fixed

           Rows: 0

 Avg_row_length: 0

    Data_length: 0

Max_data_length: 98784247807

   Index_length: 1024

      Data_free: 0

 Auto_increment: NULL

    Create_time: 2002-02-24 17:36:57

    Update_time: 2002-02-24 17:36:57

     Check_time: NULL

 Create_options: max_rows=1000000000 avg_row_length=32

        Comment:

1 row in set (0.05 sec)

可以看到,Create_options列出了创建时的选项,而且该表的最大的数据量为91GB。你可以用ALTER TABLE来改变指针的大小,但是那会导致表和索引的重建,这会花费很长的时间。

1.4.1.2、MyISAM的特性
(1)锁与并发性:MyISAM只有表级锁,不支持行级锁。所以不适合于大量的写操作,但是它支持并发插入(concurrent inserts),这是一个非常重要且有用的特性。
(2)自动修复:MySQL支持自动检查和修复MyISAM表。
(3)手动修复:你可以使用CHECK TABLE检查表的状态,并用REPAIR TABLE修复表。
(4)索引:你可以为BLOB和TEXT的前500个字符创建索引。而且,MyISAM还支持全文索引,但仅限于CHAR、VARCHAR、和TEXT列。
(5)延迟键写(Delayed key writes):如果创建MyISAM表时指定DELAY_KEY_WRITE,MySQL在查询结束时,不会将改变的索引数据写入磁盘,而将修改保存在key buffer中。只有要改变缓存或者关闭表时,才会把索引数据刷入磁盘。

1.4.2、InnoDB
InnoDB是一个高性能的事务存储引擎,此外,BDB也支持事务处理(关于BDB,以前曾较为详细的阅读过其源码,以后有时间再讨论),它有以下一些特点:
1.4.2.1、表空间
InnoDB存储表和索引有两种方式:
(1)共享表空间存储:这种方式下,表的定义位于.frm文件中,数据和索引保存在innodb_data_home_dir和innodb_data_file_path指定的表空间中。
(2)多表空间存储:表的定义仍位于.frm文件,但是,每个InnoDB表和它的索引在它自己的文件(.idb)中,每个表有它自己的表空间。
对那些想把特定表格移到分离物理磁盘的用户,或者那些希望快速恢复单个表的备份而无须打断其余InnoDB表的使用的用户,使用多表空间会是有益的。你可以往my.cnf的[mysqld]节添加下面行来允许多表空间:
[mysqld]
innodb_file_per_table
重启服务器之后,InnoDB存储每个新创建的表到表格所属于的数据库目录下它自己的文件tbl_name.ibd里。这类似于MyISAM存储引擎所做的,但MyISAM 把表分成数据文件tbl_name.MYD和索引文件tbl_name.MYI。对于InnoDB,数据和所以被一起存到.ibd文件。tbl_name.frm文件照旧依然被创建。
如果你从my.cnf文件删除innodb_file_per_table行,并重启服务器,InnoDB在共享的表空间文件里再次创建表。
innodb_file_per_table只影响表的创建。如果你用这个选项启动服务器,新表被用.ibd文件来创建,但是你仍旧能访问在共享表空间里的表。如果你删掉这个选项,新表在共享表空间内创建,但你仍旧可以访问任何用多表空间创建的表。
InnoDB总是需要共享表空间,.ibd文件对InnoDB不足以去运行,共享表空间包含熟悉的ibdata文件,InnoDB把内部数据词典和undo日志放在这个文件中。

1.4.2.2、外键约束
MySQL中,支持外键的存储引擎只有InnoDB,在创建外键时,要求被参照表必须有对应的索引,参照表在创建外键时也会自动创建对应的索引。

1.4.2.3、MVCC与后码锁(next-key locking)
InnoDB将MVCC机制与next-key lock结合起来,实现事务的各个隔离级别,这是非常用意思的。在nodb_locks_unsafe_for_binlog变量被设置或者事务的隔离级别不是SERIALIZABLE的情况下,InnoDB对于没有指定FOR UPDATE 或 LOCK IN SHARE MODE的INSERT INTO ... SELECT, UPDATE ... (SELECT), 和CREATE TABLE ... SELECT语句使用一致性读(参照前面),在这种情况下,查询语句不会对表中的元组加锁。否则,InnoDB将使用锁。

 

主要参考:

 《MySQL Manual》

 《High Performance MySQL》

(责任编辑:admin)
织梦二维码生成器
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片