执行导出数据库:
. j7 O! e: `$ b+ Z$ ?# Dmysqldump -u root -predh3 nova >/root/zhongnan-nova.sql
' \' S& z5 ]. l Y* tmysqldump: Got error: 1033: "Incorrect information in file: './nova/agent_builds.frm'" when using LOCK TABLES- m3 {/ [( C, G
报错了:. X6 m8 s @4 D* C
Got error: 1033:
1 }) Z, a: Q5 m: ^* r; s- ~when using LOCK TABLES
& p9 t0 R) }+ _解决方法授予用户锁表权限即可。 网上有人说使用 –skip-lock-tables,这个会影响数据的一致性(可能比丢数据还要遭糕),故不推荐使用这个方法。 –single-transaction 用于 Innodb 引擎的数据库 dump 时,可以不锁表。 mysql 锁表原理深入下去还有很多细节可以学习,可以参考 Ref 相关资料。 导数据库报上面错,添加参数--single-transaction . c9 N8 L) A A2 S3 N
[root@compute03 ~]# mysqldump -u root -predh3 nova --single-transaction >/root/zhongnan-nova.sql
# T* x8 U6 `1 n8 E8 c% amysqldump: Couldn't execute 'show create table `agent_builds`': Incorrect information in file: './nova/agent_builds.frm' (1033)( X. l0 c; U8 A7 C4 P
4 R2 p H' R: a+ U还是报错::
2 R$ A# l) S& R登录到数据库中show % m9 ^6 I* L; W. N& I$ C9 s
MariaDB [nova]> show create table `agent_builds` ;* X& r1 u2 `6 [. v5 j
ERROR 1033 (HY000): Incorrect information in file: './nova/agent_builds.frm'
0 W# S# a" j5 |; M* ]1 F查看数据结构:; v% z4 h" C j! b- B2 x
MariaDB [nova]> desc agent_builds;
6 X7 _, i* M6 m t$ U4 r% FERROR 1033 (HY000): Incorrect information in file: './nova/agent_builds.frm'
V* J& h( l% t/ A. A- S; F' R$ V* B# h! h x' ~$ p3 w- _# L
root@compute03 ~]# mysqldump -u root -predhat123 nova --single-transaction --skip-lock-tables >/root/zhongnan-nova.sql
3 G: {% `) Z1 P& a8 D; wmysqldump: Couldn't execute 'show create table `agent_builds`': Incorrect information in file: './nova/agent_builds.frm' (1033): q2 a7 w! F$ r+ T
( R+ w2 p, f' q3 l' U
: c" p9 _& c/ y
今天在备份一位客户的mysql数据库的时候,使用mysqldump命令备份,出现when using LOCK TABLES的提示。如果对mysql中的用户的权限进行过详细设置的话,会知道用户可以被分配LOCK TABLES和UNLOCK TABLES两个权限,使该用户在对该用户的表进行读写锁设定。# `& |* L% k: _0 ?6 k% N
遇到该问题,解决方案如下:' [6 H8 ^# z5 K2 N4 E5 ~
在执行备份的时候,将命令中添加 --skip-lock-tables,即命令如下:
|( D% T3 T) u' P mysqldump -u 用户名 -p 用户密码 --skip-lock-tables -R database > /root/database_1120.dmp
6 n2 z4 _6 B2 ^8 p/ Y# \' R2 }3 n7 ~ p
下面是对事务表使用LOCK TABLES的说明:4 P7 `. L3 E5 _( S
在尝试锁定表之前,LOCK TABLES不是事务安全型的,会隐含地提交所有活性事务。同时,开始一项事务(例如,使用START TRANSACTION),会隐含地执行UNLOCK TABLES
& m- V, n5 }- A6 t7 f+ E 对事务表(如InnoDB)使用LOCK TABLES的正确方法是,设置AUTOCOMMIT=0并且不能调用UNLOCK TABLES,直到您明确地提交事务为止。当您调用LOCK TABLES时,InnoDB会内部地取其自己的表锁定,MySQL取其自己的表锁定。InnoDB在下一个提交时释放其表锁定,但是,对于MySQL,要释放表锁定,您必须调用UNLOCK TABLES。您不应该让AUTOCOMMIT=1,因为那样的话,InnoDB会在调用LOCK TABLES之后立刻释放表锁定,并且很容易形成死锁定。注意,如果AUTOCOMMIT=1,我们根本不能获取InnoDB表锁定,这样就可以帮助旧的应用软件避免不必要的死锁定。9 k: \; ?& I9 f
ROLLBACK不会释放MySQL的非事务表锁定。" I9 _( R3 d! W2 t; m; R
要使用LOCK TABLES,您必须拥有相关表的LOCK TABLES权限和SELECT权限。2 O: v5 R( B3 O6 m' D
使用LOCK TABLES的主要原因是仿效事务,或在更新表时加快速度。这将在后面进行更详细的解释。
) _, v/ h$ J/ y8 M J) z% `8 j如果一个线程获得对一个表地READ锁定,该线程(和所有其它线程)只能从该表中读取。如果一个线程获得对一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。其它的线程被阻止,直到锁定被释放时为止。
, _- ~5 `$ f& `9 ~% @READ LOCAL和READ之间的区别是,READ LOCAL允许在锁定被保持时,执行非冲突性INSERT语句(同时插入)。但是,如果您正打算在MySQL外面操作数据库文件,同时您保持锁定,则不能使用READ LOCAL。对于InnoDB表,READ LOCAL与READ相同。
/ p8 K, B/ p |+ h 当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。虽然使用LOCK TABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,在此情况下,您必须分别获得对每个别名的锁定。
1 T1 e% `$ q- N/ w# P5 s; ymysql> LOCK TABLE t WRITE, t AS t1 WRITE;
Y- h5 {5 B* t, ^* p' Y- Q% }! Z' r! v" G
mysql> INSERT INTO t SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLES ^* z. Y: ?9 B0 A9 x- D
2 S& w& U! y( \7 ~5 smysql> INSERT INTO t SELECT * FROM t AS t1; 如果您的查询使用一个别名引用一个表,那么您必须使用同样的别名锁定该表。如果没有指定别名,则不会锁定该表。
' D. y1 G H$ @ u3 F+ J4 fmysql> LOCK TABLE t READ;
6 N3 E% i/ ^+ \+ B% |9 D7 q: z; G( d* D9 e8 V5 S+ N
mysql> SELECT * FROM t AS myalias;ERROR 1100: Table 'myalias' was not locked with LOCK TABLES相反的,如果您使用一个别名锁定一个表,您必须使用该别名在您的查询中引用该表。
* w+ ~7 @8 a1 M$ K4 mmysql> LOCK TABLE t AS myalias READ;
! `" b& i9 m& @( X( \; S9 \" Q. r) _" X1 n+ I' V; [
mysql> SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLES
) J8 g5 q4 D8 w8 k' h
# G. L5 l9 {6 ^. Wmysql> SELECT * FROM t AS myalias;
& |. s- o: y7 V. r/ yWRITE锁定通常比READ锁定拥有更高的优先权,以确保更新被尽快地处理。这意味着,如果一个线程获得了一个READ锁定,则另一个线程会申请一个WRITE锁定,后续的READ锁定申请会等待,直到WRITE线程获得锁定并释放锁定。您可以使用LOW_PRIORITY WRITE锁定来允许其它线程在该线程正在等待WRITE锁定时获得READ锁定。只有当您确定最终将有一个时机,此时没有线程拥有READ锁定时,您才应该使用LOW_PRIORITY WRITE锁定。! T( [0 B9 g, W4 E4 B
LOCK TABLES按照如下方式执行:: T9 V* h) u* D; Q
1. 按照内部定义的顺序,对所有要被锁定的表进行分类。从用户的角度,此顺序是未经定义的。; O9 V* @7 C) n3 T
2. 如果使用一个读取和一个写入锁定对一个表进行锁定,则把写入锁定放在读取锁定之前。
5 e+ n) q- H7 g3. 一次锁定一个表,直到线程得到所有锁定为止。$ F3 u' g8 i) p0 F5 U
该规则确保表锁定不会出现死锁定。但是,对于该规则,您需要注意其它的事情:( u0 I' m( P1 A/ D
如果您正在对一个表使用一个LOW_PRIORITY WRITE锁定,这只意味着,MySQL等待特定的锁定,直到没有申请READ锁定的线程时为止。当线程已经获得WRITE锁定,并正在等待得到锁定表清单中的用于下一个表的锁定时,所有其它线程会等待WRITE锁定被释放。如果这成为对于应用程序的严重的问题,则您应该考虑把部分表转化为事务安全型表。5 p8 l3 o/ z7 f; B
您可以安全地使用KILL来结束一个正在等待表锁定的线程。
: d* X9 q1 Z& @5 ^注意,您不能使用INSERT DELAYED锁定任何您正在使用的表,因为,在这种情况下,INSERT由另一个线程执行。. \- y# d3 K5 h2 Q. C
通常,您不需要锁定表,因为所有的单个UPDATE语句都是原子性的;没有其它的线程可以干扰任何其它当前正在执行的SQL语句。但是,在几种情况下,锁定表会有好处:
g6 Y* i2 m, T 如果您正在对一组MyISAM表运行许多操作,锁定您正在使用的表,可以快很多。锁定MyISAM表可以加快插入、更新或删除的速度。不利方面是,没有线程可以更新一个用READ锁定的表(包括保持锁定的表),也没有线程可以访问用WRITE锁定的表(除了保持锁定的表以外)。/ L" F- P; B1 K( |) j9 `
有些MyISAM操作在LOCK TABLES之下更快的原因是,MySQL不会清空用于已锁定表的关键缓存,直到UNLOCK TABLE被调用为止。通常,关键缓存在每个SQL语句之后被清空。
+ {9 T. V+ q$ d, ~/ ` 如果您正在使用MySQL中的一个不支持事务的存储引擎,则如果您想要确定在SELECT和UPDATE之间没有其它线程,您必须使用LOCK TABLES。本处所示的例子要求LOCK TABLES,以便安全地执行:1 g1 M- i5 s& q% o( [3 Q2 I
mysql> LOCK TABLES trans READ, customer WRITE;· # H; y3 h, p- |5 ^+ \
1 |2 L' ]( s+ M$ l+ ]. a
mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;· 8 p, }) |0 C/ L% N$ ?- h
! W! p2 t5 z5 r2 p( F& Z% x$ u
mysql> UPDATE customer· # \* t. q( @3 C: b$ y
-> SET total_value=sum_from_previous_statement·
5 A, T' X5 y, u' Q k* V -> WHERE customer_id=some_id;·
8 n6 @8 \$ q2 C( e
9 m8 r* ?6 R0 V3 d% {mysql> UNLOCK TABLES;如果没有LOCK TABLES,有可能另一个线程会在执行SELECT和UPDATE语句之间在trans表中插入一个新行。' W, ~+ D! S' \; N8 X5 |
通过使用相对更新(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函数,您可以在许多情况下避免使用LOCK TABLES。
5 @. x* n# X( P/ r# f9 R) D6 j通过使用用户层级的顾问式锁定函数GET_LOCK()和RELEASE_LOCK(),您也可以在有些情况下避免锁定表。这些锁定被保存在服务器中的一个混编表中,使用pthread_mutex_lock() 和pthread_mutex_unlock(),以加快速度。) n0 ]: R' y) H
要了解更多有关锁定规则的说明
/ a& E) R9 c. R2 m$ ]$ s您可以使用FLUSH TABLES WITH READ LOCK语句锁定位于所有带有读取锁定的数据库中的所有表。如果您有一个可以及时拍摄快照的文件系统,比如Veritas,这是获得备份的一个非常方便的方式。. h# u5 p9 ^! W$ m$ V
注释:如果您对一个已锁定的表使用ALTER TABLE,该表可能会解锁。* g) S* ~( H' E2 _8 r
" L: c9 M) c9 s- o5 {
& Q& b9 Z) w) P d1 a8 g U$ G
, v. C0 {& |0 i4 R在一个网站上看到一个解决方法:' c9 \! }& |* P4 D
1.创建一个暂存鱼眼/坩埚服务器" o! ^0 R3 `/ t# G: C
2.连接到另一个MySQL数据库服务器2 Y- H& H0 D/ _) e O; i7 L. j2 T
3.从新数据库中,复制相同的 .frm 文件以替换生产服务器中有问题的 .frm 文件6 u& o/ \/ X! M1 f- b2 f
4.重启Fisheye/Crucible生产服务器
7 \3 z: u4 Y; q* ?& G, y
: g$ y& ]0 b5 q% ?7 \
$ n( w+ Z, w) J I |