执行导出数据库:
# h) H- s8 q( L J- |8 Z5 z" Qmysqldump -u root -predh3 nova >/root/zhongnan-nova.sql + e& K4 M$ Q" V$ t7 Y) B5 f) `
mysqldump: Got error: 1033: "Incorrect information in file: './nova/agent_builds.frm'" when using LOCK TABLES
7 e* A, f+ F$ Y/ r6 L' t' Z报错了:! W" L) l7 F% h$ Z$ F
Got error: 1033: ' M( Q4 D6 l) M5 j6 D* Y
when using LOCK TABLES
. o) a' R C1 K' A: d5 n解决方法授予用户锁表权限即可。 网上有人说使用 –skip-lock-tables,这个会影响数据的一致性(可能比丢数据还要遭糕),故不推荐使用这个方法。 –single-transaction 用于 Innodb 引擎的数据库 dump 时,可以不锁表。 mysql 锁表原理深入下去还有很多细节可以学习,可以参考 Ref 相关资料。 导数据库报上面错,添加参数--single-transaction
$ a/ t& B8 E* p[root@compute03 ~]# mysqldump -u root -predh3 nova --single-transaction >/root/zhongnan-nova.sql 4 x1 b3 Q' l p
mysqldump: Couldn't execute 'show create table `agent_builds`': Incorrect information in file: './nova/agent_builds.frm' (1033)
; B7 D8 U( E; T1 c" g' [! y0 @
5 `: C% t3 H- \( Q% n( `还是报错::8 E) e, N% V# r
登录到数据库中show
+ M6 i; j( {3 e( V: a7 U6 Q; ~MariaDB [nova]> show create table `agent_builds` ;1 F1 ]6 V1 Y) q7 C8 b
ERROR 1033 (HY000): Incorrect information in file: './nova/agent_builds.frm'4 q/ L* t8 h" ?) o7 e
查看数据结构:
r# e- h: G) b8 T2 }* E& R( K8 g6 u/ CMariaDB [nova]> desc agent_builds;0 l9 i3 |( ^8 s, {# c6 S' y- D+ ?+ _
ERROR 1033 (HY000): Incorrect information in file: './nova/agent_builds.frm'
2 y( k, E" l. }6 p8 Y3 F/ y) c3 m0 t# ]* B( O; W
root@compute03 ~]# mysqldump -u root -predhat123 nova --single-transaction --skip-lock-tables >/root/zhongnan-nova.sql 9 G8 m1 x$ |" U
mysqldump: Couldn't execute 'show create table `agent_builds`': Incorrect information in file: './nova/agent_builds.frm' (1033)
% o7 x, U' \1 w* _, P4 D
3 I7 w1 @# m0 b7 Q0 W/ Y% H: m n; d, J
今天在备份一位客户的mysql数据库的时候,使用mysqldump命令备份,出现when using LOCK TABLES的提示。如果对mysql中的用户的权限进行过详细设置的话,会知道用户可以被分配LOCK TABLES和UNLOCK TABLES两个权限,使该用户在对该用户的表进行读写锁设定。" R7 ] o- R6 O' B& s9 e, H
遇到该问题,解决方案如下:: B' g1 C/ {0 A# @! Y* o, c7 N6 ~
在执行备份的时候,将命令中添加 --skip-lock-tables,即命令如下:8 r9 @2 g- \9 w3 r; c6 _
mysqldump -u 用户名 -p 用户密码 --skip-lock-tables -R database > /root/database_1120.dmp
: r# L, a" m7 x9 W3 b3 q4 s) X j; ~) @6 g: w7 u2 S) ~! Y
下面是对事务表使用LOCK TABLES的说明:
9 u, f' L" Q o 在尝试锁定表之前,LOCK TABLES不是事务安全型的,会隐含地提交所有活性事务。同时,开始一项事务(例如,使用START TRANSACTION),会隐含地执行UNLOCK TABLES
W5 q2 A8 C2 S& m$ u$ c 对事务表(如InnoDB)使用LOCK TABLES的正确方法是,设置AUTOCOMMIT=0并且不能调用UNLOCK TABLES,直到您明确地提交事务为止。当您调用LOCK TABLES时,InnoDB会内部地取其自己的表锁定,MySQL取其自己的表锁定。InnoDB在下一个提交时释放其表锁定,但是,对于MySQL,要释放表锁定,您必须调用UNLOCK TABLES。您不应该让AUTOCOMMIT=1,因为那样的话,InnoDB会在调用LOCK TABLES之后立刻释放表锁定,并且很容易形成死锁定。注意,如果AUTOCOMMIT=1,我们根本不能获取InnoDB表锁定,这样就可以帮助旧的应用软件避免不必要的死锁定。
3 B: y( ~+ E: g ROLLBACK不会释放MySQL的非事务表锁定。
8 `* ~' |2 I0 O2 S$ B& P 要使用LOCK TABLES,您必须拥有相关表的LOCK TABLES权限和SELECT权限。 O: o( m- f o# D1 J4 d6 I* u7 b
使用LOCK TABLES的主要原因是仿效事务,或在更新表时加快速度。这将在后面进行更详细的解释。
$ e2 u# N9 h' ?9 e% s6 Y) b/ A如果一个线程获得对一个表地READ锁定,该线程(和所有其它线程)只能从该表中读取。如果一个线程获得对一个表的WRITE锁定,只有保持锁定的线程可以对表进行写入。其它的线程被阻止,直到锁定被释放时为止。
; [$ N2 d! u! x" ?) q) g( TREAD LOCAL和READ之间的区别是,READ LOCAL允许在锁定被保持时,执行非冲突性INSERT语句(同时插入)。但是,如果您正打算在MySQL外面操作数据库文件,同时您保持锁定,则不能使用READ LOCAL。对于InnoDB表,READ LOCAL与READ相同。
; L& I( m) f1 ^9 C( L0 Q 当您使用LOCK TABLES时,您必须锁定您打算在查询中使用的所有的表。虽然使用LOCK TABLES语句获得的锁定仍然有效,但是您不能访问没有被此语句锁定的任何的表。同时,您不能在一次查询中多次使用一个已锁定的表——使用别名代替,在此情况下,您必须分别获得对每个别名的锁定。( S/ E; `* b# I2 ?6 I. a7 }/ V# V. T
mysql> LOCK TABLE t WRITE, t AS t1 WRITE;) a* t+ N' ~) r3 x( U' o4 L" x
& @' f9 M% V' s/ a) }mysql> INSERT INTO t SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLES. h; c/ N( n. a% f8 q! ^: j3 [
$ g( g# {, N7 \, H. Y& Y- \
mysql> INSERT INTO t SELECT * FROM t AS t1; 如果您的查询使用一个别名引用一个表,那么您必须使用同样的别名锁定该表。如果没有指定别名,则不会锁定该表。
& }% ~+ w! _- G8 bmysql> LOCK TABLE t READ; m5 M( Y+ ^3 \5 M8 u
) |- z6 q o1 Y0 Dmysql> SELECT * FROM t AS myalias;ERROR 1100: Table 'myalias' was not locked with LOCK TABLES相反的,如果您使用一个别名锁定一个表,您必须使用该别名在您的查询中引用该表。. i6 Z4 W7 K9 p! U, N: k- s; ~
mysql> LOCK TABLE t AS myalias READ;
5 s6 L+ j ^0 S2 x" ^! C! h# D- C$ g$ M& d0 [/ j/ }" q& n
mysql> SELECT * FROM t;ERROR 1100: Table 't' was not locked with LOCK TABLES
. U: `- x$ B: o- D. l# Y0 z
0 P- F4 z2 t. `' s1 Bmysql> SELECT * FROM t AS myalias;
" F, [8 [* P8 L( p7 g1 j, HWRITE锁定通常比READ锁定拥有更高的优先权,以确保更新被尽快地处理。这意味着,如果一个线程获得了一个READ锁定,则另一个线程会申请一个WRITE锁定,后续的READ锁定申请会等待,直到WRITE线程获得锁定并释放锁定。您可以使用LOW_PRIORITY WRITE锁定来允许其它线程在该线程正在等待WRITE锁定时获得READ锁定。只有当您确定最终将有一个时机,此时没有线程拥有READ锁定时,您才应该使用LOW_PRIORITY WRITE锁定。
% I* b" d. `/ GLOCK TABLES按照如下方式执行:3 M/ Z" Z8 p1 K; n* T T
1. 按照内部定义的顺序,对所有要被锁定的表进行分类。从用户的角度,此顺序是未经定义的。5 X: [7 ~" _& h* G4 J4 C
2. 如果使用一个读取和一个写入锁定对一个表进行锁定,则把写入锁定放在读取锁定之前。
" Y0 E2 J" ~$ l4 V1 t3. 一次锁定一个表,直到线程得到所有锁定为止。/ L- J) \' l& A1 E
该规则确保表锁定不会出现死锁定。但是,对于该规则,您需要注意其它的事情:# B. R9 C9 X: r0 \& O0 Y
如果您正在对一个表使用一个LOW_PRIORITY WRITE锁定,这只意味着,MySQL等待特定的锁定,直到没有申请READ锁定的线程时为止。当线程已经获得WRITE锁定,并正在等待得到锁定表清单中的用于下一个表的锁定时,所有其它线程会等待WRITE锁定被释放。如果这成为对于应用程序的严重的问题,则您应该考虑把部分表转化为事务安全型表。3 \' e" H8 A# v4 c
您可以安全地使用KILL来结束一个正在等待表锁定的线程。
8 W: E4 E3 M: T" l注意,您不能使用INSERT DELAYED锁定任何您正在使用的表,因为,在这种情况下,INSERT由另一个线程执行。
) L7 A6 Y' |0 z @- R9 d通常,您不需要锁定表,因为所有的单个UPDATE语句都是原子性的;没有其它的线程可以干扰任何其它当前正在执行的SQL语句。但是,在几种情况下,锁定表会有好处:( U# `; f: I- K0 S
如果您正在对一组MyISAM表运行许多操作,锁定您正在使用的表,可以快很多。锁定MyISAM表可以加快插入、更新或删除的速度。不利方面是,没有线程可以更新一个用READ锁定的表(包括保持锁定的表),也没有线程可以访问用WRITE锁定的表(除了保持锁定的表以外)。
! U: Q* j: w7 E- n K k* ^有些MyISAM操作在LOCK TABLES之下更快的原因是,MySQL不会清空用于已锁定表的关键缓存,直到UNLOCK TABLE被调用为止。通常,关键缓存在每个SQL语句之后被清空。
3 r3 I, @0 c; Z2 ^ 如果您正在使用MySQL中的一个不支持事务的存储引擎,则如果您想要确定在SELECT和UPDATE之间没有其它线程,您必须使用LOCK TABLES。本处所示的例子要求LOCK TABLES,以便安全地执行:7 E: U8 }2 j" y! R8 H
mysql> LOCK TABLES trans READ, customer WRITE;· . k- C# A# b% w8 O# m
# ]' G' w1 m( H1 _1 J7 Jmysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;·
6 j0 a1 z- |9 ?: Z/ _
+ v" y9 ~2 G4 t) @9 g" Emysql> UPDATE customer· % y3 W' \- X2 @2 K, E5 E# t, O
-> SET total_value=sum_from_previous_statement· # H1 U* |, P3 {8 v! r
-> WHERE customer_id=some_id;· ' g6 E" C0 l! u; }$ } u/ Q6 l
7 c/ D/ n/ p) e& b. C2 K( S& jmysql> UNLOCK TABLES;如果没有LOCK TABLES,有可能另一个线程会在执行SELECT和UPDATE语句之间在trans表中插入一个新行。6 K+ D$ B5 Y4 I# E& y/ D
通过使用相对更新(UPDATE customer SET value=value+new_value)或LAST_INSERT_ID()函数,您可以在许多情况下避免使用LOCK TABLES。
: N" M- U" l; s0 c3 k. K" _8 L i2 X; U通过使用用户层级的顾问式锁定函数GET_LOCK()和RELEASE_LOCK(),您也可以在有些情况下避免锁定表。这些锁定被保存在服务器中的一个混编表中,使用pthread_mutex_lock() 和pthread_mutex_unlock(),以加快速度。# J b) `( _% _7 k# r2 B* \4 K
要了解更多有关锁定规则的说明& O1 k S% n: \$ c) ^: g
您可以使用FLUSH TABLES WITH READ LOCK语句锁定位于所有带有读取锁定的数据库中的所有表。如果您有一个可以及时拍摄快照的文件系统,比如Veritas,这是获得备份的一个非常方便的方式。1 Y* B1 G/ t" Q
注释:如果您对一个已锁定的表使用ALTER TABLE,该表可能会解锁。" l @+ i2 {: y# L! C# {- r
$ H9 f5 Y1 ]7 Q3 p0 g5 A4 l
. u) l3 v5 f. p
4 V. O h% q3 e; f3 y在一个网站上看到一个解决方法:
& u% X% P8 ? k0 C) c8 A$ y1.创建一个暂存鱼眼/坩埚服务器# p) G4 U) m/ U" ?# b
2.连接到另一个MySQL数据库服务器
3 I: z( M# u# x2 ]3.从新数据库中,复制相同的 .frm 文件以替换生产服务器中有问题的 .frm 文件4 \7 t( j4 [: ?: K( W) v3 S
4.重启Fisheye/Crucible生产服务器
9 _2 W2 a4 U) Y. Q: F: Y- e
+ f4 d9 s; R, }
1 P9 F |1 I* G* U* Z$ W |