不应将 Base64 编码的数据存储在自己的数据库中...
Base64 是一种仅使用可打印文本字符表示任意二进制数据的编码:它设计用于需要通过只能处理可打印文本的协议或介质(例如 SMTP/电子邮件)传输此类二进制数据的情况。它增加了数据大小(增加了 33%)并增加了编码/解码的计算成本,因此除非绝对必要,否则应避免使用。
相比之下,列的全部意义BLOB
在于它们存储不透明的二进制字符串。因此,只需继续将您的内容直接存储到您的BLOB
列中,而无需先对它们进行 Base64 编码。(也就是说,如果 MySQL 有更适合存储的特定数据的类型,您可能希望使用它:例如,像 JavaScript 源代码这样的文本文件可以从存储在TEXT
MySQL 原生跟踪特定文本元数据的列中受益- 更多关于这个下面)。
SQL 数据库需要像 Base64 这样的可打印文本编码来处理任意二进制数据的(错误的)想法已经被大量信息不灵的教程所延续。这个想法似乎是基于一个错误的信念,即因为 SQL 在其他上下文中只包含可打印的文本,所以它肯定也需要二进制数据(至少对于数据传输,如果不是为了数据存储)。这根本不是真的:SQL 可以通过多种方式传达二进制数据,包括纯字符串文字(前提是它们像任何其他字符串一样被正确引用和转义);当然,将数据(任何类型)传递到数据库的首选方式是通过参数化查询,并且参数的数据类型可以很容易地成为原始二进制字符串。
...除非出于性能原因对其进行缓存...
存储 Base64 编码数据可能有一些好处的唯一情况是,它通常在从数据库中检索后立即通过需要这种编码的协议(例如通过电子邮件附件)进行传输——在这种情况下,存储 Base64 编码的数据表示将不必在每次提取时对其他原始数据执行编码操作。
但是,请注意,从这个意义上讲,Base64 编码的存储只是充当缓存,就像出于性能原因可能存储非规范化数据一样。
TEXT
...在这种情况下不应该BLOB
如上所述:TEXT
和BLOB
列之间的唯一区别是,对于TEXT
列,MySQL 还为您跟踪特定于文本的元数据(例如字符编码和排序规则)。这个额外的元数据使 MySQL 能够在存储和连接字符集(在适当的情况下)之间转换值,并执行花哨的字符串比较/排序操作。
一般来说:如果两个使用不同字符集的客户端应该看到相同的字节,那么你需要一个BLOB
列;如果他们应该看到相同的字符,那么您需要一TEXT
列。
使用 Base64,这两个客户端最终必须发现数据解码为相同的字节;但他们应该看到存储/编码的数据具有相同的字符。例如,假设有人希望插入'Hello world!'
(即'SGVsbG8gd29ybGQh'
)的 Base64 编码。如果插入应用程序使用 UTF-8 字符集工作,则它将字节序列发送0x53475673624738676432397962475168
到数据库。
如果该字节序列存储在BLOB
列中,然后由使用 UTF-16 *的应用程序检索,则将返回相同的字节'升噳扇㡧搲㥹扇全'
——它们表示而不是所需的 Base64 编码值;然而
如果该字节序列存储在TEXT
列中,然后由使用 UTF-16 的应用程序检索,则 MySQL 将即时转码以返回字节序列0x0053004700560073006200470038006700640032003900790062004700510068
——它代表所需的原始 Base64 编码值'SGVsbG8gd29ybGQh'
。
当然,您仍然可以使用BLOB
列并以其他方式跟踪字符编码——但这只会不必要地重新发明轮子,增加维护复杂性和引入意外错误的风险。
* 实际上 MySQL 不支持使用与 ASCII 字节不兼容的客户端字符集(因此 Base64 编码在它们的任何组合中总是一致的),但是这个示例仍然用于说明BLOB
和TEXT
列类型之间的区别,因此解释了为什么TEXT
在技术上对此目的是正确的,即使BLOB
实际上可以正常工作(至少在 MySQL 添加对非 ASCII 兼容客户端字符集的支持之前)。