而你的每一次
mysql
-h${HOSTNAME}
-P${PORT}
-u${USERNAME}...
都是一个新的连接(SESSION)AUTOCOMMIT=0
这个仅是对当前SESSION的变量进行了设置,并没有改变所有的MYSQL事务设置。
㈡ mysql的事务四个特性以及事务的四个隔离级别
分别是原子性、一致性、隔离性、持久性。
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。举例来说,假设用户A和用户B两者的钱加起来一共是1000,那么不管A和B之间如何转账、转几次账,事务结束后两个用户的钱相加起来应该还得是1000,这就是事务的一致性。
隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务已经正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成。否则的话就会造成我们虽然看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。这是不允许的。
在数据库操作中,在并发的情况下可能出现如下问题:
正是为了解决以上情况,数据库提供了几种隔离级别。
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted(未授权读取、读未提交)、Read committed(授权读取、读提交)、Repeatable read(可重复读取)、Serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻象读这几类问题。
虽然数据库的隔离级别可以解决大多数问题,但是灵活度较差,为此又提出了悲观锁和乐观锁的概念。
悲观锁,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度。因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制。也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统的数据访问层中实现了加锁机制,也无法保证外部系统不会修改数据。
商品t_items表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单(此时该商品无法再次下单),那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。
如果不采用锁,那么操作方法如下:
但是上面这种场景在高并发访问的情况下很可能会出现问题。例如当第一步操作中,查询出来的商品status为1。但是当我们执行第三步Update操作的时候,有可能出现其他人先一步对商品下单把t_items中的status修改为2了,但是我们并不知道数据已经被修改了,这样就可能造成同一个商品被下单2次,使得数据不一致。所以说这种方式是不安全的。
在上面的场景中,商品信息从查询出来到修改,中间有一个处理订单的过程,使用悲观锁的原理就是,当我们在查询出t_items信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为t_items被锁定了,就不会出现有第三者来对其进行修改了。需要注意的是,要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。我们可以使用命令设置MySQL为非autocommit模式: set autocommit=0;
设置完autocommit后,我们就可以执行我们的正常业务了。具体如下:
上面的begin/commit为事务的开始和结束,因为在前一步我们关闭了mysql的autocommit,所以需要手动控制事务的提交。
上面的第一步我们执行了一次查询操作: select status from t_items where id=1 for update; 与普通查询不一样的是,我们使用了 select…for update 的方式,这样就通过数据库实现了悲观锁。此时在t_items表中,id为1的那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被其它事务修改。需要注意的是,在事务中,只有 SELECT ... FOR UPDATE 或 LOCK IN SHARE MODE 操作同一个数据时才会等待其它事务结束后才执行,一般 SELECT ... 则不受此影响。拿上面的实例来说,当我执行 select status from t_items where id=1 for update; 后。我在另外的事务中如果再次执行 select status from t_items where id=1 for update; 则第二个事务会一直等待第一个事务的提交,此时第二个查询处于阻塞的状态,但是如果我是在第二个事务中执行 select status from t_items where id=1; 则能正常查询出数据,不会受第一个事务的影响。
使用 select…for update 会把数据给锁住,不过我们需要注意一些锁的级别,MySQL InnoDB默认Row-Level Lock,所以只有“明确”地指定主键或者索引,MySQL 才会执行Row lock (只锁住被选取的数据) ,否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。举例如下:
1、 select * from t_items where id=1 for update;
这条语句明确指定主键(id=1),并且有此数据(id=1的数据存在),则采用row lock。只锁定当前这条数据。
2、 select * from t_items where id=3 for update;
这条语句明确指定主键,但是却查无此数据,此时不会产生lock(没有元数据,又去lock谁呢?)。
3、 select * from t_items where name='手机' for update;
这条语句没有指定数据的主键,那么此时产生table lock,即在当前事务提交前整张数据表的所有字段将无法被查询。
4、 select * from t_items where id>0 for update; 或者 select * from t_items where id>1 for update; (注:>在SQL中表示不等于)
上述两条语句的主键都不明确,也会产生table lock。
5、 select * from t_items where status=1 for update; (假设为status字段添加了索引)
这条语句明确指定了索引,并且有此数据,则产生row lock。
6、 select * from t_items where status=3 for update; (假设为status字段添加了索引)
这条语句明确指定索引,但是根据索引查无此数据,也就不会产生lock。
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以只会在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回用户错误的信息,让用户决定如何去做。实现乐观锁一般来说有以下2种方式:
㈢ mysql数据库 事务提交怎么处理
查看 MySQL 客户端的事务提交方式命令:select @@autocommit;
修改 MySQL 客户端的事务提交方式为手动提交命令:set @@autocommit = 0;
(注:0 表示手动提交,即使用 MySQL 客户端执行 SQL 命令后必须使用commit命令执行事务,否则所执行的 SQL 命令无效,如果想撤销事务则使用 rollback 命令。1 表示自动提交,即在 MySQL 客户端不在需要手动执行 commit 命令。)
MySQL 在自动提交模式下,每个 SQL 语句都是一个独立的事务。
注意:
1、手动设置set @@autocommit = 0,即设定为非自动提交模式,只对当前的mysql命令行窗口有效,打开一个新的窗口后,默认还是自动提交;
2、对于非自动提交模式,比如在命令行中添加一条记录,退出命令行后在重新打开命令行,之前插入的记录是不在的。(用select * from + 表名 验证一下就可以了)
㈣ mysql的特点是什么
一、MySQL数据库的特点和优势:
(1)功能强大
MySQL 中提供了多种数据库存储引擎,各引擎各有所长,适用于不同的应用场合,用户可以选择最合适的引擎以得到最高性能,可以处理每天访问量超过数亿的高强度的搜索 Web 站点。MySQL5 支持事务、视图、存储过程、触发器等。
(2)支持跨平台
MySQL 支持至少 20 种以上的开发平台,包括 Linux、Windows、FreeBSD 、IBMAIX、AIX、FreeBSD 等。这使得在任何平台下编写的程序都可以进行移植,而不需要对程序做任何的修改。
(3)运行速度快
高速是 MySQL 的显着特性。在 MySQL 中,使用了极快的 B 树磁盘表(MyISAM)和索引压缩;通过使用优化的单扫描多连接,能够极快地实现连接;SQL 函数使用高度优化的类库实现,运行速度极快。
(4)支持面向对象
PHP 支持混合编程方式。编程方式可分为纯粹面向对象、纯粹面向过程、面句对象与面向过程混合 3 种方式。
(5)安全性高
灵活和安全的权限与密码系统,允许基本主机的验证。连接到服务器时,所有的密码传输均采用加密形式,从而保证了密码的安全。
(6)成本低
MySQL 数据库开放源代码且无版权制约,是一种完全免费的产品,用户可以直接通过网络下载,自主性及使用成本低。体积小,安装方便。历史悠久,用户使用活跃,遇到问题可以寻求帮助,易于维护。
(7)支持各种开发语言
MySQL 为各种流行的程序设计语言提供支持,为它们提供了很多的 API 函数,包括 PHP、ASP.NET、Java、Eiffel、Python、Ruby、Tcl、C、C++、Perl 语言等。
(8)数据库存储容量大
MySQL 数据库的最大有效表尺寸通常是由操作系统对文件大小的限制决定的,而不是由 MySQL 内部限制决定的。InnoDB 存储引擎将 InnoDB 表保存在一个表空间内,该表空间可由数个文件创建,表空间的最大容量为 64TB,可以轻松处理拥有上千万条记录的大型数据库。
(9)支持强大的内置函数
PHP 中提供了大量内置函数,几乎涵盖了 Web 应用开发中的所有功能。它内置了数据库连接、文件上传等功能,MySQL 支持大量的扩展库,如 MySQLi 等,可以为快速开发 Web 应用提供便利。
二、相比其他数据库的特点和优势:
(1) 对事务的提交
MySQL默认是自动提交,不需要在写commit指令或者点击commit按钮。
(2) 分页查询
MySQL是直接在SQL语句中写"select... from ...where...limit m, n",有limit就可以实现分页。PHP里还可以用SEEK定位到结果集的位置。
(3) 事务隔离级别
MySQL是read commited的隔离级别。
一个session读取数据时,其他session不能更改数据,但可以在表最后插入数据。session更新数据时,要加上排它锁,其他session无法访问数据。
(4) 复制简单
MySQL复制服务器配置简单。
(5) 自动增长的数据类型处理
MYSQL有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值。
(6)单引号的处理
MYSQL里可以用双引号包起字符串。
(7) 日期字段的处理
MYSQL日期字段分DATE和TIME两种。
(8)空字符的处理
MYSQL的非空字段也有空的内容,NULL或空字符。
㈤ 安装MySQL事务数据库都需要哪些步骤
按常规的方法进行安装
安装MySQL完成后,启动MySQL(和PHP搭配之最佳组合)binWinMySQL(和PHP搭配之最佳组合)admin
再退出
运行
MySQL(和PHP搭配之最佳组合)binmydqld-nt--remove
MySQL(和PHP搭配之最佳组合)binMySQL(和PHP搭配之最佳组合)d-max-nt--install
以上二行是去掉不支持事务处理的MySQL(和PHP搭配之最佳组合)服务,改成支持MySQL(和PHP搭配之最佳组合)事务处理的服务
然后在c:下建一个ibdata目录及iblogs目录,当然名字可以不一样,记住这二个名字及盘符,以后要用到,你也可以不建在C盘,然后,打开c:winnt或c:windows目录下的my.ini,在最后添加:以下内容为程序代码:
1.innodb_data_file_path=ibdata1:2000M;ibdata2:2000M
2.innodb_data_home_dir=c:ibdata
3.set-variable=innodb_mirrored_log_groups=1
4.innodb_log_group_home_dir=c:iblogs
5.set-variable=innodb_log_files_in_group=3
6.set-variable=innodb_log_file_size=30M
7.set-variable=innodb_log_buffer_size=8M
8.innodb_flush_log_at_trx_commit=1
9.innodb_log_arch_dir=c:iblogs
10.innodb_log_archive=0
11.set-variable=innodb_buffer_pool_size=80M
12.set-variable=innodb_additional_mem_pool_size=10M
13.set-variable=innodb_file_io_threads=4
14.set-variable=innodb_lock_wait_timeout=50
其中
1.innodb_data_file_path=ibdata1:2000M;ibdata2:2000M 这一行中的2000M可以自己改成200m,看你盘的容量大小,MySQL(和PHP搭配之最佳组合)推荐10G及以上的硬盘空间最好用这样的设置;
以下这一行
1.innodb_data_home_dir=c:ibdata 也可以改成你自己起的目录,主要是看你自己在刚才建的目录在哪里啦
按照以上的方法,你已经安装MySQL好了MySQL(和PHP搭配之最佳组合)的事务数据库,不过你要是按照MySQL(和PHP搭配之最佳组合)手册上的方法安装,把上面的一段配制放到my.cnf是去的话,可是会出错哦
好了,现在让我们试试看是不是安装完成了,启动apache(Unix平台最流行的WEB服务器平台),或iis,在服务里启动MySQL(和PHP搭配之最佳组合)的服务,打开phpmyadmin,输入:SHOWvariableslikehave_%
你要是看到下面的结果,那说明你安装MySQL成功了
以下内容为程序代码
1.Variable_nameValue
2.have_bdbYES
3.have_innodbYES
4.have_isamYES
5.have_raidNO
6.have_symlinkYES
7.have_opensslNO
8.have_query_cacheYES
9. 注:MySQL(和PHP搭配之最佳组合)的事务处理方法的使用同其它数据库语法相似,在这里我就不多说了,另外,MySQL(和PHP搭配之最佳组合)将在4.3中实现外键及子查询,简单的外键已经在4.0中都已经实现了,只是不怎么方便,相信以后会做得更好些。
㈥ 谈谈你对 mysql 事务的认识 我是php初学者不懂这个 想请教大神教我
先简单介绍一下事务吧!事务是DBMS得执行单位。它由有限得数据库操作序列组成得。但不是任意得数据库操作序列都能成为事务。一般来说,事务是必须满足4个条件(ACID)
原子性(Autmic):事务在执行性,要做到“要么不做,要么全做!”,就是说不允许事务部分得执行。即使因为故障而使事务不能完成,在rollback时也要消除对数据库得影响!
一致性(Consistency):事务得操作应该使使数据库从一个一致状态转变倒另一个一致得状态!就拿网上购物来说吧,你只有即让商品出库,又让商品进入顾客得购物篮才能构成事务!
隔离性(Isolation):如果多个事务并发执行,应象各个事务独立执行一样!
持久性(Durability):一个成功执行得事务对数据库得作用是持久得,即使数据库应故障出错,也应该能够恢复!
MYSQL的事务处理主要有两种方法。
1、用begin,rollback,commit来实现
begin
开始一个事务
rollback 事务回滚
commit 事务确认
2、直接用set来改变mysql的自动提交模式
MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们可以通过
set autocommit=0
禁止自动提交
set autocommit=1 开启自动提交
来实现事务的处理。
但注意当你用 set
autocommit=0
的时候,你以后所有的SQL都将做为事务处理,直到你用commit确认或rollback结束,注意当你结束这个事务的同时也开启了个新的事务!按第一种方法只将当前的作为一个事务!
个人推荐使用第一种方法!
MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持的!(切记!)
下次有空说下MYSQL的数据表的锁定和解锁!
MYSQL5.0 WINXP下测试通过~ ^_^
mysql> use test;
Database
changed
mysql> CREATE TABLE `dbtest`(
-> id int(4)
-> ) TYPE=INNODB;
Query OK, 0 rows affected, 1 warning (0.05
sec)
mysql> select * from dbtest
-> ;
Empty set (0.01
sec)
mysql> begin;
Query OK, 0 rows affected (0.00
sec)
mysql> insert into dbtest value(5);
Query OK, 1 row affected
(0.00 sec)
mysql> insert into dbtest value(6);
Query OK, 1 row
affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00
sec)
mysql> select * from dbtest;
+------+
| id
|
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00
sec)
mysql> begin;
Query OK, 0 rows affected (0.00
sec)
mysql> insert into dbtest values(7);
Query OK, 1 row affected
(0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00
sec)
mysql> select * from dbtest;
+------+
| id
|
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00
sec)
mysql>
*******************************************************************************************************************
[PHP]
function
Tran( $sql ) {
$judge = 1;
mysql_query('begin');
foreach ($sql as $v) {
if
( !mysql_query($v) ) {
$judge =
0;
}
}
if ($judge == 0)
{
mysql_query('rollback');
return
false;
}
elseif ($judge == 1) {
mysql_query('commit');
return true;
}
}
[/PHP]
************************************************
<?php
$handler=mysql_connect("localhost","root","");
mysql_select_db("task");
mysql_query("SET
AUTOCOMMIT=0");//设置为不自动提交,因为MYSQL默认立即执行
mysql_query("BEGIN");//开始事务定义
if(!mysql_query("insert
into trans (id)
values('2')"))
{
mysql_query("ROOLBACK");//判断当执行失败时回滚
}
if(!mysql_query("insert
into trans (id)
values('4')"))
{
mysql_query("ROOLBACK");//判断执行失败回滚
}
mysql_query("COMMIT");//执行事务
mysql_close($handler);
?>
引自:http://www.cnblogs.com/in-loading/archive/2012/02/21/2361702.html
㈦ mysql怎么给操作两个数据库的sql加事务
mysql一般表使用innodb引擎才能使用事务,请先确定表引擎为innodb
㈧ mysql proxy是否支持事务,是否支持跨库
MySQL Proxy 支持事务,读写分离就会把这个作为切分转发依据之一;
也支持跨库,但是不晓得你是否问的事务跨库?这个就不清楚了、谁知道请补充。
参考:
http://dev.mysql.com/doc/refman/5.6/en/mysql-proxy-using.html
http://dev.mysql.com/doc/refman/5.6/en/mysql-proxy-faq.html
㈨ Mysql数据库中,事务是指什么如何使用该功能
什么是事务? x0dx0ax0dx0a事务是逻辑上的一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务 x0dx0ax0dx0a注意:mysql数据支持事务,但是要求必须是innoDB存储引擎 x0dx0ax0dx0a解决这个问题: x0dx0ax0dx0amysql的事务解决这个问题,因为mysql的事务特性,要求这组操作,要不全都成功,要不全都失败,这样就避免了某个操作成功某个操作失败。利于数据的安全 x0dx0ax0dx0a如何使用: x0dx0ax0dx0a(1)在执行sql语句之前,我们要开启事务 start transaction; x0dx0ax0dx0a(2)正常执行我们的sql语句 x0dx0ax0dx0a(3)当sql语句执行完毕,存在两种情况: x0dx0ax0dx0a1,全都成功,我们要将sql语句对数据库造成的影响提交到数据库中,committ x0dx0ax0dx0a2,某些sql语句失败,我们执行rollback(回滚),将对数据库操作赶紧撤销 x0dx0ax0dx0a(注意:mysql数据支持事务,但是要求必须是innoDB存储引擎) x0dx0amysql> create table bank(name varchar(20),money decimal(5,1))engine=innodb defau x0dx0alt charset=utf8; x0dx0ax0dx0amysql> inset into bank values('shaotuo',1000),('laohu',5000); x0dx0ax0dx0amysql> select*from bank; x0dx0a+---------+--------+ x0dx0a| name | money | x0dx0a+---------+--------+ x0dx0a| shaotuo | 1000.0 | x0dx0a| laohu | 5000.0 | x0dx0a+---------+--------+ x0dx0ax0dx0a------没有成功“回滚”执行rollback x0dx0amysql> start transaction; //开启事务 x0dx0aQuery OK, 0 rows affected (0.00 sec) x0dx0ax0dx0amysql> update bank set money=money+500 where name='shaotuo' x0dx0aQuery OK, 1 row affected (0.00 sec) x0dx0aRows matched: 1 Changed: 1 Warnings: 0 x0dx0ax0dx0amysql> update bank set moey=money-500 where name='laohu' x0dx0aERROR 1054 (42S22): Unknown column 'moey' in 'field list' x0dx0amysql> rollback; //只要有一个不成功,执行rollback操作 x0dx0aQuery OK, 0 rows affected (0.01 sec) x0dx0ax0dx0amysql> select*from bank; x0dx0a+---------+--------+ x0dx0a| name | money | x0dx0a+---------+--------+ x0dx0a| shaotuo | 1000.0 | x0dx0a| laohu | 5000.0 | x0dx0a+---------+--------+ x0dx0a------成功之后 进行commit操作 x0dx0amysql> start transaction; //开启事务 x0dx0aQuery OK, 0 rows affected (0.00 sec) x0dx0ax0dx0amysql> update bank set money=money+500 where name='shaotuo' x0dx0aQuery OK, 1 row affected (0.01 sec) x0dx0aRows matched: 1 Changed: 1 Warnings: 0 x0dx0ax0dx0amysql> update bank set money=money-500 where name='laohu' x0dx0aQuery OK, 1 row affected (0.00 sec) x0dx0aRows matched: 1 Changed: 1 Warnings: 0 x0dx0ax0dx0amysql> commit; //两个都成功后执行commit(只要不执行commit,sql语句不会对真实的数据库造成影响) x0dx0aQuery OK, 0 rows affected (0.05 sec) x0dx0ax0dx0amysql> select*from bank; x0dx0a+---------+--------+ x0dx0a| name | money | x0dx0a+---------+--------+ x0dx0a| shaotuo | 1500.0 | x0dx0a| laohu | 4500.0 | x0dx0a+---------+--------+
㈩ Mysql某个表有近千万数据,CRUD比较慢,如何优化
数据千万级别之多,占用的存储空间也比较大,可想而知它不会存储在一块连续的物理空间上,而是链式存储在多个碎片的物理空间上。可能对于长字符串的比较,就用更多的时间查找与比较,这就导致用更多的时间。
可以做表拆分,减少单表字段数量,优化表结构。
在保证主键有效的情况下,检查主键索引的字段顺序,使得查询语句中条件的字段顺序和主键索引的字段顺序保持一致。
主要两种拆分 垂直拆分,水平拆分。
垂直分表
也就是“大表拆小表”,基于列字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。 一般是针对 那种 几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。
垂直分库针对的是一个系统中的不同业务进行拆分,比如用户User一个库,商品Proct一个库,订单Order一个库。 切分后,要放在多个服务器上,而不是一个服务器上。为什么? 我们想象一下,一个购物网站对外提供服务,会有用户,商品,订单等的CRUD。没拆分之前, 全部都是落到单一的库上的,这会让数据库的单库处理能力成为瓶颈。按垂直分库后,如果还是放在一个数据库服务器上, 随着用户量增大,这会让单个数据库的处理能力成为瓶颈,还有单个服务器的磁盘空间,内存,tps等非常吃紧。 所以我们要拆分到多个服务器上,这样上面的问题都解决了,以后也不会面对单机资源问题。
数据库业务层面的拆分,和服务的“治理”,“降级”机制类似,也能对不同业务的数据分别的进行管理,维护,监控,扩展等。 数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。 数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈。
水平分表
针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。不建议采用。
水平分库分表
将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。
水平分库分表切分规则
1. RANGE
从0到10000一个表,10001到20000一个表;
2. HASH取模
一个商场系统,一般都是将用户,订单作为主表,然后将和它们相关的作为附表,这样不会造成跨库事务之类的问题。 取用户id,然后hash取模,分配到不同的数据库上。
3. 地理区域
比如按照华东,华南,华北这样来区分业务,七牛云应该就是如此。
4. 时间
按照时间切分,就是将6个月前,甚至一年前的数据切出去放到另外的一张表,因为随着时间流逝,这些表的数据 被查询的概率变小,所以没必要和“热数据”放在一起,这个也是“冷热数据分离”。
分库分表后面临的问题
事务支持
分库分表后,就成了分布式事务了。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价; 如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
跨库join
只要是进行切分,跨节点Join的问题是不可避免的。但是良好的设计和切分却可以减少此类情况的发生。解决这一问题的普遍做法是分两次查询实现。在第一次查询的结果集中找出关联数据的id,根据这些id发起第二次请求得到关联数据。
跨节点的count,order by,group by以及聚合函数问题
这些是一类问题,因为它们都需要基于全部数据集合进行计算。多数的代理都不会自动处理合并工作。解决方案:与解决跨节点join问题的类似,分别在各个节点上得到结果后在应用程序端进行合并。和join不同的是每个结点的查询可以并行执行,因此很多时候它的速度要比单一大表快很多。但如果结果集很大,对应用程序内存的消耗是一个问题。
数据迁移,容量规划,扩容等问题
来自淘宝综合业务平台团队,它利用对2的倍数取余具有向前兼容的特性(如对4取余得1的数对2取余也是1)来分配数据,避免了行级别的数据迁移,但是依然需要进行表级别的迁移,同时对扩容规模和分表数量都有限制。总得来说,这些方案都不是十分的理想,多多少少都存在一些缺点,这也从一个侧面反映出了Sharding扩容的难度。
ID问题
一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键生成机制。一方面,某个分区数据库自生成的ID无法保证在全局上是唯一的;另一方面,应用程序在插入数据之前需要先获得ID,以便进行SQL路由.
一些常见的主键生成策略
UUID
使用UUID作主键是最简单的方案,但是缺点也是非常明显的。由于UUID非常的长,除占用大量存储空间外,最主要的问题是在索引上,在建立索引和基于索引进行查询时都存在性能问题。
Twitter的分布式自增ID算法Snowflake
在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位 机器ID 10位 毫秒内序列12位。
跨分片的排序分页
一般来讲,分页时需要按照指定字段进行排序。当排序字段就是分片字段的时候,我们通过分片规则可以比较容易定位到指定的分片,而当排序字段非分片字段的时候,情况就会变得比较复杂了。为了最终结果的准确性,我们需要在不同的分片节点中将数据进行排序并返回,并将不同分片返回的结果集进行汇总和再次排序,最后再返回给用户。